1.var
for(var j=0;j<3;j++){
setTimeout(() => {
console.log(j,'j')
}, 0);
}
//输出结果 3,3,3
因为j时全局环境中声明的变量,我们自始至终赋值、修改都是同一个j变量
2.let
let:让js有了块级作用域。用let声明的变量,不存在变量提升。而且要求必须 等let声明语句执行完之后,变量才能使用。在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。let变量不能重复声明
for (let i=0;i<3;i++){
setTimeout(() => {
console.log(i,'i')
}, 0);
}
哈哈哈,他输出的结果是0,1,2
但是 有没有同学觉得 let既然是块级的话,每次循环都是一个新变量,输出的应该是0。
下面就是解释为什么不是0
来自阮一峰老师的解释 ---链接https://es6.ruanyifeng.com/#docs/let
上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是1,2,3。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
总结:
1>在for 中使用let 块级的时候,每次循环都是独立存在的
2> 那他是怎么知道当前循环时第几次呢?因为js引擎会帮我们记住
3.setTimeOut(func,time)函数运行机制
既然上面例子中提到setTimeOut那么我就在这里提一下
浏览器引擎按顺序执行程序,遇到setTimeout会将func函数放到执行队列中,等到主程序执行完毕之后,才开始从执行队列(队列中可能有多个待执行的func函数)中按照time延时时间的先后顺序取出来func并执行。即使time=0,也会等主程序运行完之后,才会执行。
上面为什么会用闭包其实也是作用域问题,这个匿名函数自调用,就是让它不必等待主程序运行完成。记录当前的q值,创建一个单独的作用域。