📜  下面的代码片段打印出什么?我们如何修复匿名函数以使其行为符合我们的预期? (1)

📅  最后修改于: 2023-12-03 15:35:54.135000             🧑  作者: Mango

修复匿名函数行为的方法

问题描述

我们有如下的代码片段:

for (var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, i * 1000);
}

我们期待的输出是每隔一秒打印一个数字,从0到4。但实际上,该程序会每隔一秒打印5个数字5,而不是从0到4。这是为什么呢?

原因是因为 setTimeout 的回调函数是异步执行的,当 for 循环执行完成后,i 的值已经变为了5。因此当回调函数被执行时,它会打印出5个数字5。

修复方法

要修复该程序,我们需要使用闭包来捕获当前的i值,以便在回调函数中使用。具体做法是在 setTimeout 函数中定义一个立即执行的匿名函数,在该匿名函数内返回一个新的匿名函数,该新函数会使用闭包捕获当前的i值并将其返回,这样回调函数就可以使用该值了。

for (var i = 0; i < 5; i++) {
    (function(j) {
        setTimeout(function() {
            console.log(j);
        }, j * 1000);
    })(i);
}

在上面的代码中,我们定义了一个立即执行的匿名函数,该函数将当前的i值作为参数传递给一个新的匿名函数,该新函数使用闭包捕获了该i值,并在回调函数中使用它。这样我们就可以得到我们期待的输出了,即每隔一秒打印一个数字,从0到4。

总结

使用闭包来修复匿名函数的行为是一个常见的技巧,它能够解决很多类似的问题。在编写 JavaScript 的时候,我们应该时刻记住异步执行和闭包的特点,以便更好地应对这些问题。