var let setTimeOut 经典面试题
for (var i = 1; i <= 5; i++) {setTimeout( function timer() {console.log(i);}, i * 1000 );
}//要求改动上述代码,使其依次输出1、2、3、4、5
每过1秒钟输出了一个数字6,5个6
当同步代码执行完毕后,开始执行异步的setTimeout代码,执行setTimeout时需要从当前作用域内寻找一个变量 i ,此时for循环已执行完毕,当前 i=6,所以执行setTimeout时输出为6,任务队列中的剩余4个setTimeout也依次执行,输出为6。
用立刻执行函数包裹,把i传进去,就是闭包
for (var i = 1; i <= 5; i++) {(function(i){ //用立刻执行函数包裹,把i传进去setTimeout( function timer() {console.log(i);}, i * 1000 );})(i);
}
用立刻执行函数。这样 console.log(i); 中的i就保存在每一次循环生成的立刻执行函数中的作用域里了。
块级作用域–关键字let
使用闭包可以得到正确的结果,原因就是改变了i的作用域,那如果我们把循环中的每个setTimeout都独立成一个作用域是不是也能实现同样的结果呢?
我们都知道,在JavaScript中,每个函数是一个独立的作用域,但是“{}”是不能形成独立作用域的。
在ES6中提出了一个新的关键字let,就可以声明一个仅对当前“{}”内部有作用的变量。
let是块级作用域,每执行一次setTimeout就向每个块中寻找i值,执行了5次,每个块中分别是1 2 3 4 5,所以结果为 1 2 3 4 5
最后结果是1s后 1 2 3 4 5
var let 经典面试题(理解作用域)
详解setTimeOut面试题
for循环 + setTimeout 结合的烂大街的面试题