Javascript范围和调用函数

时间:2011-07-21 14:40:05

标签: javascript

我的代码:

for (var i = 0; i < mapInfos.length; i++) {

            var x = function () { doStuff(i); };
            google.maps.event.addListenerOnce(mapInfos[i].map, 'tilesloaded', x);
}

doStuff方法只是警告i的值。 mapInfos有两个条目,所以你希望它提醒0和1,而是它警告2和2.我可以隐约感谢它为什么这样做(虽然var我应该把它保持在循环范围的本地?)但我怎样才能让它按预期工作呢?

5 个答案:

答案 0 :(得分:8)

编辑 - 请注意,首次发布时,原始问题包含link to a jsfiddle,这似乎是当前问题尝试实现的相关示例,只是它似乎有效...


jsfiddle中的代码有效,因为该代码中只有一个“i”。在第二个循环中使用的“i”(实际上调用函数)与第一个循环中使用的“i”相同。因此,您得到了正确的答案,因为第二个循环正在“i”运行从零到四个的所有值。如果您添加:

i = 100;
functions[0]();
你打印出100张。

在JavaScript中引入新范围的唯一方法是函数。一种方法是编写一个单独的“函数制造者”函数:

function makeCallback(param) {
  return function() {
    doStuff(param);
  };
}

然后在你的循环中:

for (var i = 0; i < mapInfos.length; i++) {
  var x = makeCallback(i);
  google.maps.event.addListenerOnce(mapInfos[i].map, 'titlesloaded', x);
}

这样做是因为对“makeCallback”函数的调用将“i”值的副本隔离到返回的闭包中新的“param”实例中。

答案 1 :(得分:1)

为它创建一个新范围。

功能创建范围。

function doStuffFactory(i) {
    return function () { doStuff(i); };
}

for (var i = 0; i < mapInfos.length; i++) {
    var x = doStuffFactory(i);
    google.maps.event.addListenerOnce(mapInfos[i].map, 'tilesloaded', x);
}

答案 2 :(得分:1)

将其更改为

var x = function (param) { doStuff(param); };

显然,正在发生的是你正在警告正在改变的变量。通过上述更改,它会复制它,即使我更改它仍然会提醒正确的值。

答案 3 :(得分:0)

Javascript 具有阻止范围,因此获得循环本地的x。是啊!

它有功能范围。

答案 4 :(得分:0)

是的,奇怪的不是它!Pointy有一个解释

我不知道为什么你的第一个例子有效(我没想到) Pointy解释了为什么你的第一个例子有效 - 你的第二个例子不是因为i的范围限定为包含for循环的函数,而不是for循环定义的范围。实际上 JavaScript中唯一具有范围的东西就是函数。这意味着当函数执行时i2

您需要做的是创建一个范围,例如:

for (var i = 0; i < mapInfos.length; i++) {

    var x = (function() {
        return function () { doStuff(i); };
    })(i);
    google.maps.event.addListenerOnce(mapInfos[i].map, 'tilesloaded', x);
}

有关详情,请参阅JavaScript closures in for-loops