Kwin Huang

不会搞艺术的程序员不是好设计师.

在循环中使用闭包

2019-09-27

面试

编写一个函数,该函数将遍历整数列表,并在延迟3秒后打印每个元素的索引。

经常不正确的写法是这样的:

const arr = [1, 2, 3, 4, 5];

for (var i = 0; i < arr.length; i++) {
  setTimeout(function() {
    console.log(i);
  }, 3000);
}
// 如果运行上面的代码, 3秒后你会看到 打印 5个5, 而不是0,1,2,3,4

原因是因为 setTimeout 函数创建了一个可以访问其外部作用域的函数(闭包),该作用域是包含索引 i 的循环。 经过 3 秒后,执行该函数并打印出 i 的值,该值在循环结束时为 4,因为它循环经过0,1,2,3,4并且循环最终停止在 4。

实际上有多处方法来正确的解这道题:

const arr = [1, 2, 3, 4, 5];

for (var i = 0; i < arr.length; i++) {
  setTimeout(function(i_local){
    return function () {
      console.log(i_local);
    }
  }(i), 3000)
}

或者

const arr = [1, 2, 3, 4, 5];

for (let i = 0; i < arr.length; i++) {
  setTimeout(function(){
    console.log(i);
  }, 3000)
}