我的代码:
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我应该把它保持在循环范围的本地?)但我怎样才能让它按预期工作呢?
答案 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中唯一具有范围的东西就是函数。这意味着当函数执行时i
为2
。
您需要做的是创建一个范围,例如:
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。