Javascript setTimeout回调解释
我不明白如何解释下面的代码以及为什么它不能按预期工作:Javascript setTimeout回调解释,javascript,node.js,lexical-scope,Javascript,Node.js,Lexical Scope,我不明白如何解释下面的代码以及为什么它不能按预期工作: for (var i = 0; i < 16; i++) { setTimeout(function () { console.log(i); }, 1) } // Prints "16" 16 times 一个自调用函数 如果我对此有一个有根据的猜测,那就是var的作用域绑定到函数块,或者在全局作用域的情况下,for循环将击败调用堆栈,setTimeout()将产生,并且由于Javascrip
for (var i = 0; i < 16; i++) {
setTimeout(function () {
console.log(i);
}, 1)
}
// Prints "16" 16 times
一个自调用函数
如果我对此有一个有根据的猜测,那就是var的作用域绑定到函数块,或者在全局作用域的情况下,for循环将击败调用堆栈,
setTimeout()
将产生,并且由于Javascript在词汇范围内,它以var i=16
的形式调用所有这些函数,而另一方面let i=16
将其保留在块中?在第一个示例中,循环变量i
周围有一个闭包。在第二种情况下,您可以通过复制i
而不是使用k
来避免这种情况。避免闭包允许每个迭代保留自己的值,而不是与所有迭代共享i
。使用let
也可以解决这个问题,因为它会使循环变量i
具有块级范围,这意味着在每次迭代中,i
在技术上是一个与前一个不同的变量,因此每个嵌套函数都会获得对不同值的引用
这都是因为JavaScript中的作用域如何工作以及嵌套函数如何导致闭包,当嵌套函数引用高阶函数中的变量并且嵌套函数的寿命比父函数长时,闭包会对代码产生副作用。在您的情况下,
setTimeout
引用的函数将比其包含的函数寿命更长。在第一个示例中,循环变量i
周围有一个闭包。在第二种情况下,您可以通过复制i
而不是使用k
来避免这种情况。避免闭包允许每个迭代保留自己的值,而不是与所有迭代共享i
。使用let
也可以解决这个问题,因为它会使循环变量i
具有块级范围,这意味着在每次迭代中,i
在技术上是一个与前一个不同的变量,因此每个嵌套函数都会获得对不同值的引用
这都是因为JavaScript中的作用域如何工作以及嵌套函数如何导致闭包,当嵌套函数引用高阶函数中的变量并且嵌套函数的寿命比父函数长时,闭包会对代码产生副作用。在您的情况下,
setTimeout
引用的函数将比其包含的函数寿命更长。setTimeout
在i
为16的循环后执行。请参阅setTimeout
在i
为16的循环后执行。请参阅
for (var i = 0; i < 16; i++) {
(function (k) {
setTimeout(function () {
console.log(k);
}, 100)
})(i)
}
// Print "0" to "15"