共计 1608 个字符,预计需要花费 5 分钟才能阅读完成。
根据大佬的 github 的讲解,来巩固 js。感谢大佬的分享与讲解
1、var、let、const
for (var i = 0; i < 3; i++) {setTimeout(() => console.log(i), 1)
}//3,3,3
for (let i = 0; i < 3; i++) {setTimeout(() => console.log(i), 1)
}//0,1,2
由于 JavaScript 的事件循环,setTimeout 回调会在遍历结束后才执行。因为在第一个遍历中遍历 i 是通过 var 关键字声明的,所以这个值是全局作用域下的。在遍历过程中,我们通过一元操作符 ++ 来每次递增 i 的值。当 setTimeout 回调执行的时候,i 的值等于 3。在第二个遍历中,遍历 i 是通过 let 关键字声明的:通过 let 和 const 关键字声明的变量是拥有块级作用域(指的是任何在 {} 中的内容)。在每次的遍历过程中,i 都有一个新值,并且每个值都在循环内的作用域中。
事件队列(Task Queue)。
js 引擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。当一个异步事件返回结果后,js 会将这个事件加入与当前执行栈不同的另一个队列,我们称之为事件队列。被放入事件队列不会立刻执行其回调,而是等待当前执行栈中的所有任务都执行完毕,主线程处于闲置状态时,** 主线程 ** 会去查找事件队列是否有任务。如果有,那么主线程会从中取出排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码...,如此反复,这样就形成了一个无限的循环。这就是这个过程被称为“** 事件循环(Event Loop**)”的原因。
当当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行
2、this 指向问题。
this 永远指向最后调用它的那个对象
const shape = {
radius: 10,
diameter() {return this.radius * 2},
perimeter: () => 2 * Math.PI * this.radius}
shape.diameter()//20
shape.perimeter()//NAN
例 2.
var name = "windows";
var a = {
name : "in",
func1: function () {console.log(this.name)
},
func2: function () {
var _this = this;
setTimeout(function() {_this.func1()
},100);
// setTimeout(()=> {// _this.func1()
// },100);
}
};
a.func2() // in _this=this
a.func2() // in 箭头函数
a: 箭头函数
箭头函数的 this 始终指向函数定义时的 this,而非执行时。箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this 为 undefined。
b: 通过给_this =this 将 this 绑定到固定值
c:apply,call,bind
var name = "windows";
var a = {
name : "in",
func1: function () {console.log(this.name)
},
func2: function () {
var _this = this;
setTimeout(function() {_this.func1()
}.apply(a),100);
// setTimeout(()=> {// this.func1()
// }.call(a),100);
// setTimeout(()=> {// this.func1()
// }.bind(a)(),100);
}
};
bind 是创建一个新的函数,必须要手动去调用:
正文完
发表至: javascript
2019-08-29