前端面试之var和let

195 阅读1分钟

正常循环中var和let在循环中输入的结果是一样的

  for (var j = 0; j < 5; j++) {
    console.log('var', j);
  }
  for (let i = 0; i < 5; i++) {
    console.log('let', i);
  }
  输出的结果都是一致的 0 1 2 3 4

在异步的执行中,因为线程和作用域的问题,结果会大不相同

  for (var j = 0; j < 5; j++) {
    setTimeout(() => {
      console.log('var', j);
    }, 1000);
  }
  // 输出5次5
  for (let i = 0; i < 5; i++) {
    setTimeout(() => {
      console.log('let', i);
    }, 1000);
  }
  // 输出 0 1 2 3 4

这是因为setTimeout是异步执行,每一次for循环的时候,setTimeout都执行一次,但是里面的函数没有被执行,而是被放到了任务队列里,等待执行。只有主线上的任务执行完,才会执行任务队列里的任务。也就是说它会等到for循环全部运行完毕后,才会执行fun函数,但是当for循环结束后此时i的值已经变成了5,因此虽然定时器跑了5秒,控制台上的内容依然是5。

for循环头部的let不仅将i绑定到for循环中,事实上它将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。

还可以使用闭包解决var的问题

  for (var j = 0; j < 5; j++) {
    ((j) => {
      setTimeout(() => {
        console.log('var', j);
      }, 1000);
    })(j)
  }

使用闭包,绑定函数每次的作用域。有点与let类似