本文是整理了JS中的一些重点,难点,以及不好理解的知识点
本文非常详细,深入的讲解,包学包会

1.1 函数(Function)是什么?
函数可以看做是功能(以一辆汽车为例,如下图),这些都可以看做成是方法

1.2 一个最简单的函数及触发方法
我的第一个方法
1.3 带参数的函数(形参与实参)
形参 : 函数中定义的变量(此时是没有值的,只是一个代称)
实参 : 在运行时的函数调用时传入的参数(实际的值)
js中,方法中即使定义了形参,调用时不传实参也不会报错
1.4 带有返回值的函数 ———— return
function fn(a, b){
return a*b;
}
// 调用并给num赋值
let num = fn(3, 5);
console.log(num) // 得到15
1.5 js函数内置对象 ———— arguments(重点,考点)
它是函数一创建就有的
是一个类数组(并不是真正的数组)
方法调用时,可以得到所有传进来的参数
你传多少,我就能拿到多少
function fn(){
console.log(arguments)
}
fn(1, 2, 3, 4);

经典应用 ———— 求一组参数的总和
function fn(){
let sum = 0;
for(let i = 0; i < arguments.length; i++){
sum += arguments[i];
}
// 返回 sum
return sum
}
let allSum = fn(1, 2, 3, 4);
console.log(allSum) // 得到10
1.6 函数内的变量
在函数内的定义的变量均为局部变量
函数运行完之后就会销毁(垃圾回收机制),所以外界无法访问
变量应尽量避免重名(局部与全局变量可能会混淆,导致一些意料之外的问题)
function fn() {
// 此为局部变量
let a = 5;
console.log(a)
}
fn();
console.log(a) // 此处报错,无法访问
1.7 匿名函数(难点)
顾名思义指的是没有名字的函数
必须采用下面的语法,否则会报错
(function (){
//由于没有执行该匿名函数,所以不会执行匿名函数体内的语句。
console.log(“666”);
})
匿名自执行函数(类似于JS的单例模式)
(function (){
console.log("666"); // 此处会打印666
})()
2.1 HTML事件
常用事件整理
事件名
说明
onchange()
HTML 元素改变(一般用于表单元素)
onclick ()
用户点击 HTML 元素
onmouseover()
用户在一个HTML元素上移动鼠标
onmouseout()
用户从一个HTML元素上移开鼠标
onkeydown()
用户按下键盘按键
onkeyup()
键盘按键弹起
onload()
浏览器已完成页面的加载
2.2 JavaScript 事件一般用于做什么?
2.3 事件实例
3. JavaScript 对象
在JS里 —— 万物皆为对象

3.1 对象定义
对象是变量的容器
写法以键值对的方式(键名:键值)
键值对称之为对象的属性
循环对象一般用 for in
// 对象定义
let person = {
firstName:“ouyang”,
lastName:“xiu”,
age:18
};
// 循环对象
for(let key in person){
console.log(key); // 键名
console.log(person[key]) // 键值
}
3.2 大厂经典面试题分析
let obj = Object.create(null) 与 let obj = {} 有什么区别?
之前腾讯面试的时候,问了这个问题:对象字面量创建对象与 Object.create(null)创建对象有什么区别?
一开始是有点懵的,不都是创建对象么,能有啥不同,后面我去试了一下,结果发现还蛮有意思:
let obj = {};
let obj2 = Object.create(null);
console.log(obj);
console.log(obj2)
控制台打印

乍一看,好像没啥区别,都是一个花括号
然而,展开后,确实大有不同

Object.create(null)创建的对象是非常纯净的,没有任何其它元素
而另一个let创建的对象是带有_proto_的,下面有一些方法与属性,这便是js的原型链继承,它继承了Object的方法和属性。这便是区别。
所以这种区别导致了使用场景不同

此属性是函数特有的
每个函数都会默认添加一个
用于继承属性和方法
// 创建构造函数
function Person(name, age) {
this.age = age;
this.name= name;
this.fn = function(){
console.log(this.name)
}
}
// 创建实例
let person1 = new Person(“小明”, 18);
let person2 = new Person(“小红”, 20);
person1.fn(); // 继承父级的方法
person2.fn();
console.log(person1)
console.log(person2)
执行结果

要添加一个新的属性需要在在构造器函数中添加:
function Person(name, age, sex) {
// sex为新属性
this.sex = sex;
this.age = age;
this.name= name;
this.fn = function(){
console.log(this.name)
}
}
4.1 prototype 继承
所有的 JavaScript 对象都会从一个 prototype(原型对象)中继承属性和方法:
所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例
4.2 添加属性和方法
function Person(name, age, sex) {
// sex为新属性
this.sex = sex;
this.age = age;
this.name= name;
this.fn = function(){
console.log(this.name)
}
}
Person.prototype.newVal = "我是新添加在原型上的值";
let person1 = new Person("小明", 18);
console.log(person1)

5.1 从this说起
如何解决this指向问题?

使用ES6中箭头函数
函数内部使用_this = this
使用apply,call,bind方法
new实例化一个对象
5.2 谈谈apply,call,bind
apply()
let obj = {
name : “小明”,
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout( function () {
this.func1()
}.apply(name),1000);
}
};
obj.func2() // 小明
apply() 方法调用一个函数,其具有一个指定的this值,以及作为一个数组(或者类似数组的对象)提供的参数,fun.apply(thisArg, [argsArray])
thisArg:在fun函数运行时指定的this值。指定this的值并不一定是函数执行时真正的this值,如果是原始值的this会指向该原始值的自动包装对象。
argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给fun函数。参数为null或者undefined,则表示不需要传入任何参数。
call()
let obj2 = {
name : “小红”,
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout( function () {
this.func1()
}.call(name),1000);
}
};
obj2.func2() // 小红
call() 调用一个函数,其具有一个指定的this值,以及若干个参数列表,fun.call(thisArg, arg1, arg2, …)
thisArg:在fun函数运行时指定的this值。指定this的值并不一定是函数执行时真正的this值,如果是原始值的this会指向该原始值的自动包装对象。
arg1, arg2, …:若干个参数列表
bind()
let obj3 = {
name : “小猪”,
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout( function () {
this.func1()
}.bind(name)(),1000);
}
};
obj3.func2() // 小猪
bind() 创建一个新的函数,当被调用时,将其this的关键字设置为提供的值,在调用新函数时,在任何提供一个给定的参数序列。
bind创建了一个新函数,必须手动去调用。
5.3 区别

事件冒泡:事件开始由最具体的元素接受,然后逐级向上传播

事件捕捉:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的(与上面相反)
DOM事件流:三个阶段:事件捕捉,目标阶段,事件冒泡
7.1 函数防抖


应用场景(数据抖动问题)
let telInput = document.querySelector('input');
telInput.addEventListener('input', function(e) {
//如果直接每次发请求,会导致性能问题
//数据请求
let timeOut = null;
if(timeOut){
clearTimeout(timeOut)
}else{
timeOut = setTimeout(()=>{
$.ajax({})
},2000)
}
})
7.2 函数节流
应用场景(客运站问题)
把整个事件处理器比喻成客运站,如果客运大巴到站就走,那么路上肯定会发生交通拥堵,而且车大部分是空的
因为没给时间上客,虚假繁忙的情况肯定是不好的,那么怎么处理呢?
设置一个时间间隔,时间间隔内只允许执行一次,客运站大巴设定一个时间,到点才会走
let throttle = function(func, delay) {
let prev = Date.now();
return function() {
var context = this;
var args = arguments;
var now = Date.now();
if (now - prev >= delay) {
func.apply(context, args);
prev = Date.now();
}
}
}
function demo() {
//do something
//ajax({})
//…
}
box.addEventListener(‘touchmove’, throttle(demo, 2000));

8.1 为什么要有虚拟dom?
8.2 虚拟dom是什么?好处是?
function Person(name) {
this.name = name
this.sayName= function () {
console.log(`我是 ${this.name}!`)
}
}
function myNew(that, ...args) {
const obj = Object.create(null)
obj.__proto__ = that.prototype
const res = that.call(obj, ...args)
return res instanceof Object ? res : obj
}
let person= myNew(Person, '小明')
person.sayWorld(); // 我是小明
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
1. 希望本文能对大家有所帮助,如有错误,敬请指出
2. 原创不易,还请各位客官动动发财的小手支持一波(关注、评论、点赞、收藏)
3. 拜谢各位!

先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦