Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript setTimeout回调解释_Javascript_Node.js_Lexical Scope - Fatal编程技术网

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"