使用自执行函数来实现变量的独立性

4

可能是重复问题:
JavaScript循环内的闭包-简单实用的示例

我正在尝试使用自执行函数,以便objects中的每个函数都返回不同的消息。

<script type="text/javascript">

    objects = {};

    for( var i = 0; i < 10; i++ ) {

        objects['function'+i] = function () {

            var text = ( function() { return "I am object " + i; } )();

            return text;

        };

    }

    for( var j = 0; j < 10; j++ ) {

        document.write( objects['function'+j]() + "<br>" );

    }

</script>

到目前为止,以上代码会得到以下结果:

我是对象10

我是对象10

我是对象10

我是对象10

我是对象10

我是对象10

我是对象10

我是对象10

我是对象10

我是对象10

如何使用自调用函数立即设置消息,而不受不确定的 i 的限制呢?

1
( function(index) { return "I am object " + index; } )(i); - Shmiddty
4个回答

8
你需要传递迭代器变量,这样你的匿名函数才能将其存储在自己的激活对象/词法环境记录中(即在其自己的上下文对象中)。
此外,你需要让这个匿名函数包装所有访问点。
objects[ 'function' + i ] = function( i ) {

    var text = function() { return "I am object " + i; };

    return text;

}( i );

1

您需要构建一个闭包封闭该特定的i变量并返回与i无关的函数:

for (var i = 0; i < 10; i++) {
    objects['function'+i] = ( function (num) {
        return function() {
            var text = "I am object " + num;
            return text;
        };
    } )( i ); // <== put the variable into the self-invoking function
}

1
我在这方面总是有点挑剔: OP使用的函数已经是一个闭包。您使用了一个自调用函数引入了一个新的上下文,但那不一定是一个闭包。但是,由自调用返回的函数必须是闭包(也许这就是您指的...只是想澄清一下)。 - Felix Kling
他这样做吗?我认为返回另一个函数的函数(在这里是我的IEFE)才是闭包,而不是被返回的函数。 - Bergi
@Bergi - 问题在于涉及到 i 的闭包。原帖的作者需要避免它,而不是“构建”它。 - RobG
我在 OP 的代码中没有看到任何闭包。他有一个函数,在函数内部他使用了一个多余的 IEFE。 - Bergi
1
被分配给 objects['function'+i] 的函数是一个闭包...它可以访问变量 i,即它封闭i。从技术上讲,每个 JavaScript 函数都是一个闭包,因为它们总是可以访问在更高作用域中定义的变量。解决循环中的闭包问题的方法是创建一个新的作用域。 - Felix Kling
没错,我错过了那个,因为它没有离开它定义的范围。从技术上讲,你是正确的。 - Bergi

0
你需要一个闭包.. 在这里看看King Resig的解释http://ejohn.org/apps/learn/#59。但是为了让这段代码能够工作,你必须确保当函数被调用时i的值得到了维护...所以它应该类似于:

http://jsbin.com/uveluw/1/edit

for( var i = 0; i < 10; i++ ) (function(i){

    objects['function'+i] = function () {
        var text = ( function() { return "I am object " + i; } )();
        return text;
    };

})(i)

你需要一个闭包——哎呀,恰恰相反。原帖作者需要避免使用闭包。 - RobG
不,我很确定我们正在构建一个闭包来封装i,这样外部循环就不再具有该变量的作用域了...请参见https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures。 - Justin Bicknell
外部的 i 始终是“在范围内”的,并且始终存在于闭包中,将值分配给局部变量意味着使用局部变量,而不是 i(请注意,您可以使用相同的名称用于局部变量并获得相同的效果)。 - RobG

0

立即执行返回值,以便 i 能够在循环中被关闭:

objects = {};
for( var i = 0; i < 10; i++ ) {
    objects['function'+i] = (function () {
        var text = ( function() { return "I am object " + i; } )();
        return text;
    })();
}

for( var j = 0; j < 10; j++ ) {
    console.log( objects['function'+j] );
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接