以下语句(ES6)在控制台打印出来的“i”和“timeCount”值不同,原理是什么?

代码如下:

let timeCount = 0;
for (let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log("i..", i);
    console.log("timeCount..", timeCount);
  }, 1000 * timeCount);
  timeCount ++;
}

i打印出来是从0到4,timeCount一直是5,原理是什么呢?

阅读 3.2k
6 个回答

就是一直说的闭包
i之所以没事是因为用了let相当于

let timeCount = 0;
for (let i = 0; i < 5; i++) {
    {
        let j = i;//实际上并没有 只是为了说明i在作用域在{}里

        setTimeout(() => {
            console.log("i..", j);
            console.log("timeCount..", timeCount);
        }, 1000 * timeCount);
        timeCount++;
    }

}

而如果你把i放到全局作用域将会都是5

let timeCount = 0;
let i = 0;
for (; i < 5; i++) {
  setTimeout(() => {
    console.log("i..", i);
    console.log("timeCount..", timeCount);
  }, 1000 * timeCount);
  timeCount ++;
}
let timeCount = 0;
for (let i = 0; i < 5; i++) {
  setTimeout(() => {
**alert(2)**
    console.log("i..", i);
    console.log("timeCount..", timeCount);
  }, 1000 * timeCount);
**alert(1)**
  timeCount ++;
}

setTimeout即使时间设置为0,也是有延迟的啊,加粗的地方alert你就可以看到,会先执行setTimout的下边,五次之后开始执行setTimeout,所以timeCount已经加到了5

哎……日经问题……

请自行搜索:“块级作用域”

很简单啊。
因为for循环先执行,然后再去执行异步的setTimeout

for执行完了timeCount就是5了,再去执行setTimeout内的打印不就是5个5了!

而i是因为在循环内用了块级变量let

for (let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log("i..", i);    // 1234
  }, 100);
}

1、let绑定作用域
2、你注册了5个setTimeout,等到执行的时候timeCount已经改变了

js中[所有异步的]回调函数永远在正常代码执行完之后才执行,哪怕是settimeout延迟0毫秒也改变不了他是回调函数的本质。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题