javascript
for (var i = 0; i < 10; i++) {
setTimeout(() => {console.log(i)}, 1000);
} // 10个10
for (let i = 0; i < 10; i++) {
setTimeout(() => {console.log(i)}, 1000);
} // 0 - 9
为什么
展开看看
javascript
var i; // 声明变量 i
i = 0;
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
i++;
if (i < 10) {
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
}
i++;
if (i < 10) {
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
}
i++;
if (i < 10) {
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
}
i++;
if (i < 10) {
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
}
// ...重复以上步骤直到 i = 10
i++;
if (i < 10) {
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
}
// 最终 i = 10,所有 setTimeout 回调函数访问的都是同一个 i,值为 10。
那let呢
javascript
{
let i = 0;
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
}
{
let i = 1;
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
}
{
let i = 2;
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
}
{
let i = 3;
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
}
// ...重复以上步骤直到 i = 9
{
let i = 9;
setTimeout(() => { console.log(i); }, 1000); // 设定定时器
}
// 每个 setTimeout 回调函数访问的都是不同的块级作用域中的 i,值分别为 0 到 9。
初始化部分 (
initialization
):在循环开始时执行一次。例如,在for (var i = 0; i < 10; i++)
中,var i = 0
是初始化部分,这个语句在循环开始时只执行一次。条件部分 (
condition
):每次循环迭代开始前都会进行检查。如果条件为true
,则继续执行循环体;如果为false
,则终止循环。例如,在i < 10
是条件部分,在每次循环迭代开始前都会检查i
是否小于10
。循环体:如果条件部分的结果为
true
,则执行循环体中的代码。例如:javascriptjavascript复制代码 for (var i = 0; i < 10; i++) { console.log(i); }
在第一次迭代中,
console.log(i)
会输出0
。迭代部分 (
iteration
):每次循环体执行完毕后都会执行。例如,在i++
是迭代部分,这个语句会在每次循环体执行完毕后执行一次,增加i
的值。
我的理解是:let中,每次i++都是跳出逻辑主体的作用域执行的