来自 You Don't Know JS :

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


6
6
6
6
6

但是像这样使用 IIFE
for (var i=1; i<=5; i++) {
    (function(){
        var j = i;
        setTimeout( function timer(){
            console.log( j );
        }, j*1000 );
    })();
}


1
2
3
4
5

我的问题:为什么不
for (var i=1; i<=5; i++) {
    setTimeout( function timer(){
        var j = i;
        console.log( j );
    }, i*1000 );
}

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

像 IIFE 示例一样工作?在我看来,他们都有一个带有新变量 functionj 声明,这不会创建一个具有 i 特定设置的新词法范围吗?

最佳答案

IIFE 的重要部分是它立即运行;在 i 更改之前,它会读取其值并将其放入一个新变量中。其他示例中读取 i 的函数 - function timer() - 不会立即运行,它放入新变量的值是 i 已更改后的值。

此外,在 ES6 中,您可以只使用 let i = … 而不是 var i = … 并且它可以在没有 IIFE 或 j 的情况下正常工作:

for (let i = 1; i <= 5; i++) {
    setTimeout(function timer() {
        console.log(i);
    }, i * 1000);
}


因为 let 具有块作用域而不是函数作用域,并且在 for 循环的初始化部分中声明的变量算作是 for 块内的一半。

关于javascript - 为什么需要 IIFE 来创建一个新的范围?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50615610/

10-12 06:55