JavaScript - 在函数内部保存变量而不调用函数

时间:2011-01-30 15:58:03

标签: javascript scope

有人可以用JavaScript谜语帮助我吗?

考虑以下JavaScript代码:

var a[];

for (i=0;i<10;i++)
{
    a[i] = function(){alert ("I am " + i);};
}

a[5]();

现在很明显,最后一行将导致警报显示“我是9”,而不是“我是5”,因为i的值在for结束时为9循环。

我希望警报打印“它应该是什么”,但不改变我从数组中调用函数的方式,即 - 没有参数。

我收到的提示:尝试定义一个调用另一个函数的函数。

请帮忙!!!谢谢: - )

5 个答案:

答案 0 :(得分:6)

你收到的提示有点欺骗性。你不想定义一个调用另一个的函数(你有同样的问题)。相反,你想要定义一个返回另一个。

示例: http://jsfiddle.net/sX92Q/

var a = [];

for (i = 0; i < 10; i++) {
    a[i] = alertFunc(i);
}

   // return a function that closes around the proper value of "i"
function alertFunc(i){
    return function() {
        alert(i);
    };
};

a[5]();

这实际上与在循环中使用匿名函数的那些相同,但它更有效,因为每次迭代都不需要重建匿名函数。

通常,您不希望在循环中创建重复的函数。


旁注。在javascript中,这个:

var a[];

应该是:

var a = [];

答案 1 :(得分:4)

这有效:

var a = [];

for (i=0;i<10;i++)
{
    a[i] = (function(i) {
        return function(){alert ("I am " + i);};
    })(i);
}

a[5]();

在您的示例中,匿名函数保存对i变量的引用,但是在创建函数后修改此变量。所以在你调用函数时,你会看到修改后的值。

为避免这种情况,您必须复制该变量,这就是上面的代码所做的。

或者,在Javascript 1.7中,您将使用let定义:

for (i=0;i<10;i++)
{
    let j = i;
    a[i] = function(){alert ("I am " + j);};
}

答案 2 :(得分:1)

以下代码可以使用:

var a[];

for (i=0;i<10;i++)
{
    a[i] = (function(i) {
        return function(){alert ("I am " + i);};
   })(i);
}

a[5]();

此处i转换为本地变量。

答案 3 :(得分:1)

var a[];

for (i=0;i<10;i++)
{
    a[i] = function(){alert ("I am " + i);};
}

a[i = 5]();

作弊(i = 5)=== 5

请勿执行此操作

使用上述真实解决方案之一。

或者:

var a = [];

for (i=0;i<10;i++)
{
    (function(j) {
        a[j] = function() { 
            alert ("I am " + j);
        };
    }(i)) 
}

a[i]();

使用闭包使j成为i

的当前值

答案 4 :(得分:0)

您的第一个示例不起作用的原因是,数据必须存储在某处。您有十个不同的值要存储,但只有一个 i 变量,因此它不起作用。

其他海报建议使用闭包,这是有效的,但你的问题是寻找一种方法来做它没有调用函数。我建议这个:

var a = [];
for (i=0; i<10; i++) {
  a[i] = function(i){alert("I am " + i);};
}
a[5](5);

当然这让人怀疑,为什么当他们都做同样的事情时,甚至会有十种不同的功能呢?为什么不呢:

var whoAmI = function(i){ alert("I am " + i); };
whoAmI(5);

也许您需要一个可以传递给某个外部API的函数,该API不带参数调用它?在这种情况下,做闭包函数 - 那使得函数成为事物。