请解释这两个代码块在事件循环中的输出之间的区别?

Please explain the difference between the output of these two code blockes in event-loops?

我正在学习事件循环 JavaScript 但我发现在事件循环代码块中使用关键字 let 和 var 的这种未知行为。但是当使用它们简单的循环时它们工作得很好。 请在这方面帮助我。代码块如下:

for (let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log("let keyword output : ", i);
  }, 0);
}

for (var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log("var keyword output : ", i);
  }, 0);
}

他们的输出分别如下:

let keyword output :  0
let keyword output :  1
let keyword output :  2
let keyword output :  3
let keyword output :  4

var keyword output :  5
var keyword output :  5
var keyword output :  5
var keyword output :  5
var keyword output :  5

区别在于 varlet 变量的范围。

var 中,您有一个函数作用域,因此只有一个共享绑定。使用 let 你有一个块作用域,你每次迭代都会得到一个新的绑定。

由于闭包,您在循环内声明的函数可以访问其作用域和父作用域中的所有变量,直到垃圾收集器打开。

可以在 this 已回答的问题中找到更多详细信息。

当您使用“var”定义变量时,您的变量作用域是函数作用域,或者如果它是在函数外部声明的,那么它就是全局作用域。 在您的示例中,首先将执行所有同步代码,并且所有 setTimeOut() 将被移动到“回调队列”,然后在所有同步代码完成并且 main 清除之后,setTimeOuts(异步代码)将被推送到 main 并执行一个一个 .

变量: 当你像我提到的那样用“var”删除“i”时,它的功能范围是和 因为“i”的声明不在不同的函数中 全局范围和所有日志的值将是最后一个值“for” 分配给它的循环 (5).

让 : 当你用“let”声明“i”时,它是块范围,因为日志在 不同的块每个日志的“i”值会不同。

“let”和“var”的区别与事件循环无关 这个异步示例只是向您展示了不同之处。 试试这个你会看到“j”的值对于每个日志都是不同的:

for (var i = 0; i < 5; i++) {
  let j = i;
  setTimeout(() => {
    console.log("var keyword output : ", i, j);
  }, 0);
}

这意味着“i”在每次迭代中都有不同的值,但因为它的值在下一次迭代中被覆盖,而且它是全局范围的,所有日志记录的值都是最后一个并且是相同的