for循环内部是一个块级作用域
原文链接:https://blog.csdn.net/yijun9588/article/details/89091723
JS中的for循环体比较特殊,每次执行都是一个全新的独立的块作用域
for (var i = 0; i < 3; i++) {
setTimeout(function() { // 同步注册回调函数到 异步的 宏任务队列。
console.log(i); // 执行此代码时,同步代码for循环已经执行完成
}, 0);
}
// 输出结果
3 3 3
分析:定时器为异步执行,for循环的执行速度很快,当真正执行到函数体时,此时i早已变成3,所以结果不想而知。
循环展开如下(var具备变量提升,且不支持块级作用域,所以如下代码只有一个全局变量i)
var i;
{
var i = 0;
setTimeout(function() {
console.log(i);
}, 0);
}
{
var i = 0; i++;
setTimeout(function() {
console.log(i);
}, 0);
}
{
var i = 0; i++; i++;
setTimeout(function() {
console.log(i);
}, 0);
}
{
var i = 0; i++; i++; i++;
}
如果把 var改成 let声明:
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i); // i 是循环体内局部作用域,不受外界影响。
}, 0);
}
// 输出结果:
0 1 2
分析:let支持块级作用域,var不支持(var只有函数作用域和全局作用域),所以let声明的变量只在它所在的代码块有效。
循环展开如下(let没有变量提升,且支持块级作用域,所以如下代码每个块内都有一个独立的i)
let i;
{
let i = 0;
setTimeout(function() {
console.log(i);
}, 0);
}
{
let i = 0; i++;
setTimeout(function() {
console.log(i);
}, 0);
}
{
let i = 0; i++; i++;
setTimeout(function() {
console.log(i);
}, 0);
}
{
let i = 0; i++; i++; i++;
}