正常循环中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类似