setTimeout回调解释



我不明白如何解释下面的代码,以及为什么它不像预期的那样工作:

for (var i = 0; i < 16; i++) {
    setTimeout(function () {
        console.log(i);
    }, 1)
}
// Prints "16" 16 times
一个解决方案是在for循环中使用let而不是var,或者
for (var i = 0; i < 16; i++) {
    (function (k) {
        setTimeout(function () {
            console.log(k);
        }, 100)
    })(i)
}
// Print "0" to "15"

一个自调用函数。

如果我能有一个有根据的猜测,这将是var的作用域绑定到函数块,或者在全局作用域的情况下,循环将击败setTimeout()将产生的调用堆栈,因为Javascript是词法作用域,它回调所有这些函数作为var i = 16,另一方面let i = 16将保持它块?

在第一个示例中,在循环变量i周围有一个闭包。在第二种情况下,您可以通过复制i并使用k来避免这种情况。避免闭包允许每个迭代保持自己的值,而不是与所有迭代共享i。使用let也可以解决问题,因为它将使循环变量i具有块级作用域,这意味着在每次迭代中,i在技术上将是与前一个不同的变量,因此每个嵌套函数将获得对不同值的引用。

这都是因为JavaScript中的作用域和嵌套函数导致闭包的方式,当嵌套函数引用高阶函数的变量并且嵌套函数的寿命比父函数长时,这对代码有副作用。在您的例子中,setTimeout引用的函数将比包含它的函数存活的时间更长。

最新更新