我想做以下事情:
for (var i = 0; i < 10; ++i) {
createButton(x, y, function() { alert("button " + i + " pressed"); }
}
这样做的问题是我总是得到 的最终值,i
因为 Javascript 的闭包不是按值的。
那么我怎样才能用 javascript 做到这一点呢?
我想做以下事情:
for (var i = 0; i < 10; ++i) {
createButton(x, y, function() { alert("button " + i + " pressed"); }
}
这样做的问题是我总是得到 的最终值,i
因为 Javascript 的闭包不是按值的。
那么我怎样才能用 javascript 做到这一点呢?
如果您为使用 JavaScript 1.7 或更高版本的浏览器编码,一种解决方案是使用let
关键字:
for(var i = 0; i < 10; ++i) {
let index = i;
createButton(x, y, function() { alert("button " + index + " pressed"); }
}
从 MDC 文档中心:
let 关键字导致创建具有块级作用域的 item 变量,从而为 for 循环的每次迭代创建一个新的引用。这意味着为每个闭包捕获一个单独的变量,解决共享环境带来的问题。
查看MDC 文档中心了解传统方法(创建另一个闭包)。
for(var i = 0; i < 10; i++) {
(function(i) {
createButton(function() { alert("button " + i + " pressed"); });
})(i);
}
请注意,JSLint 不喜欢这种模式。它抛出“不要在循环中创建函数。”。
现场演示: http : //jsfiddle.net/simevidas/ZKeXX/
通过执行另一个函数为闭包创建一个新的作用域:
for(var i = 0; i < 10; ++i) {
createButton(x,y, function(value) { return function() { alert(...); }; }(i));
}
您需要将闭包放入一个单独的函数中。
for(var dontUse = 0; dontUse < 10; ++dontUse) {
(function(i) {
createButton(x, y, function() { alert("button " + i + " pressed"); }
})(dontUse);
}
此代码创建了一个匿名函数,该函数i
将循环的每次迭代作为参数。
由于这个匿名函数i
每次迭代都有一个单独的参数,它解决了这个问题。
这相当于
function createIndexedButton(i) {
createButton(x, y, function() { alert("button " + i + " pressed"); }
}
for(var i = 0; i < 10; ++i) {
createIndexedButton(i);
}
for(var i = 0; i < 10; ++i) {
createButton(x, y, (function(n) {
return function() {
alert("button " + n + " pressed");
}
}(i));
}
外部的匿名函数会被自动调用,并n
在其作用域内创建一个新的闭包,每次调用时都会获取当时的当前值i
。