1、从setTimeout运行机制理解JS运行机制
(参考: https://blog.csdn.net/m0_37686205/article/details/88775880)
主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop。
setTimeout 和setInterval的运行机制是将指定的代码移出本次执行,等到下一轮Event Loop
时,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就等到再下一轮Event Loop 时重新判断。
setTimeout指定的代码,必须等到本次执行的所有同步代码都执行完,才会执行。
for (var i = 0; i < 4; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
复制代码输出结果为,隔1s后一起输出:4 4 4 4
这道题涉及了异步、作用域、闭包
settimeout是异步执行,1000ms后往任务队列里面添加一个任务,只有主线上的全部执行完,才会执行任务队列里的任务,当主线执行完成后,i是4,所以此时再去执行任务队列里的任务时,i全部是4了。对于打印4次是:4
每一次for循环的时候,settimeout都执行一次,但是里面的函数没有被执行,而是被放到了任务队列里面,等待执行,for循环了4次,就放了4次,当主线程执行完成后,才进入任务队列里面执行。
(注意:for循环从开始到结束的过程,需要维持几微秒或几毫秒。)
循环中使用闭包解决 var 定义函数的问题
1)、用let定义i
for (let i = 0; i < 4; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
因为let i 的是区块变量,每个i只能存活到大括号结束,并不会把后面的for循环的 i 值赋给前面的setTimeout中的i;而var i 则是局部变量,这个 i 的生命周期不受for循环的大括号限制;
2)、用闭包
for(var i=0;i<4;i++){
(function(i){
setTimeout(function(){
console.log(i)
},1000*i)
})(i)
}
利用立即执行函数,当for循环执行时,就会立即执行setTimeout,从而使得到的每个副本i值都不一样,这样就可以得到想要的for循环
(关于立即执行函数:https://blog.csdn.net/Liu_yunzhao/article/details/90641956)
3)、setTimeout 的第三个参数
for ( var i=1; i<=5; i++) {
setTimeout( function timer(j) {
console.log( j );
}, i*1000, i);
}
2、从作用域链谈闭包
如何理解闭包?
闭包是指有权訪问另外一个函数作用域中的变量的函数
转 载:http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
1、定义和用法:当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数内部的其它变量,如果返回的这个函数在外部被执行,就产生了闭包。
2、表现形式:使函数外部能够调用函数内部定义的变量
for循环内的闭包问题
const Greeters = []
for (var i = 0 ; i < 10 ; i++) {
Greeters.push(function () { return console.log(i) })
}
Greeters[0]() // 10
Greeters[1]() // 10
Greeters[2]() // 10
//由于这个闭包的关系,他是循环完毕之后才返回,最终结果是9++是5
//这个匿名函数里面根本没有i这个变量,所以匿名函数会从父级函数中去找i,
//当找到这个i的时候,for循环已经循环完毕了,所以最终会返回10
匿名函数的this指向
转载:https://blog.csdn.net/u013250416/article/details/40869287
**
**1**