【问题标题】:How to get current loop iteration from anonymous function within the for loop? [duplicate]如何从 for 循环中的匿名函数获取当前循环迭代? [复制]
【发布时间】:2011-11-18 00:41:50
【问题描述】:
可能重复:
Javascript closure inside loops - simple practical example
我有一个内部带有匿名函数的 for 循环,并且在该函数中我想访问当前循环迭代。但是由于某种原因而不是循环迭代,我得到了 4。唯一的另一个地方 4 是一个值是 myArray.length。如果我将 i 作为参数传递,我会得到 [object Object]。我究竟做错了什么?我的代码:
var width = function(){
for(var i = 0, len = myArray.length; i < len; ++i){
alert(i) //this outputs the current iteration
myArray[i].load(function(){
alert(i) //this outputs 4 (or [object Object])
});
};
};
谢谢。
【问题讨论】:
标签:
javascript
loops
for-loop
iteration
【解决方案1】:
你传递给.load的匿名函数在你的循环结束后被执行。
您必须创建一个本地范围,并复制 i 变量:
var width = function(){
for(var i = 0, len = myArray.length; i < len; ++i){
(function(i){
myArray[i].load(function(){
alert(i) //this outputs 4 (or [object Object])
});
})(i);
};
};
【解决方案2】:
ECMAScript 5 包括bind()[docs],用于获取具有this 值的函数以及绑定到它的参数值。
function loader( i ){
alert( i );
}
var width = function(){
for(var i = 0, len = myArray.length; i < len; ++i){
alert( i );
myArray[i].load( loader.bind( null, i ) );
}
};
在这里,我将null 绑定为返回函数中的this 值,但您可以将其设置为其他值。然后我将i 的当前值绑定为第一个参数。
要获得对旧版浏览器的支持(如果需要),请添加 shim from MDN:
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") // closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be fBound is not callable");
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP ? this : oThis || window, aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
这是一个大部分兼容的垫片,适用于大多数情况。