[英]How to get outer loop index inside anonymous function call?
我有以下javascript代码:
var Person = [['John', 0, 0, 0],['Chris', 1, 0, 0]];
for (i = 0; i < Person.length; i++ )
{
someObj.myMethod(Person[i][0], function (object) {
console.log(i); //this prints 2, I want 0 and 1 as per the loop
//here I want to access other members of Person[i] array, like Person[i][1], Person[i][2] and Person[i][3]
//but these console.log() print 'undefined' because i = 2 !!
console.log(Person[i][1]);
console.log(Person[i][2]);
console.log(Person[i][3]);
});
}
在我的myMethod()里面调用的匿名函数里面,i的值是'2'。 请建议如何在for循环的第一个循环中获得i = 0,然后在第二个循环中获得1。
有了一个闭包,这个解决方案:
var Person = [['John', 0, 0, 0],['Chris', 1, 0, 0]];
for (x = 0; x < Person.length; x++ )
{
(function(i){ //We add a closure
someObj.myMethod(Person[i][0], function (object) {
console.log(i);
console.log(Person[i][1]);
console.log(Person[i][2]);
console.log(Person[i][3]);
});
})(x); //Call the closure function with the value of the counter
}
我将原始计数器更改为x
以使其更容易理解(因此您不要将该变量与原始i
混淆),但如果它仍然命名为i
,它也会起作用。
这样,每个循环周期都有自己的变量x
( 不共享 ),所以它不会被for循环覆盖,导致问题( i
被共享):)
干杯
你有一个漏洞关闭 。 尝试这个:
var Person = [['John', 0, 0, 0],['Chris', 1, 0, 0]];
for (i = 0; i < Person.length; i++ )
{
doIt(i);
}
function doIt(i) {
someObj.myMethod(Person[i][0], function (object) {
console.log(i); //this prints 2, I want 0 and 1 as per the loop
//here I want to access other members of Person[i] array, like Person[i][1], Person[i][2] and Person[i][3]
//but these console.log() print 'undefined' because i = 2 !!
console.log(Person[i][1]);
console.log(Person[i][2]);
console.log(Person[i][3]);
});
}
基本上,你原来的内部匿名函数正被传递到别处以便稍后执行,在哪个阶段, i
变量已经在for循环中递增到2
(它们实际上引用了i
的一个副本)。 Javascript是函数作用域,所以引入一个新函数和它自己的参数来捕获i
的特定值,你可以将你的匿名函数与for循环中的共享计数器分离。
请注意,您也可以使函数(在我的示例中为doIt
)像Edgar一样立即执行匿名函数,这意味着没有其他人可以调用逻辑上的私有闭包函数(尽管它可能会让某些人更难读用于javascript闭包)。
它完全取决于何时执行回调。 如果它们立即执行,则在循环运行时,值将如您所愿。 以下输出0
和1
:
var someObj = {
myMethod: function(person, callback) {
callback();
}
}
var Person = [['John', 0, 0, 0],['Chris', 1, 0, 0]];
for (i = 0; i < Person.length; i++ )
{
someObj.myMethod(Person[i][0], function (object) {
console.log(i);
});
}
但是,如果稍后存储并执行回调,那么(这是理解的关键)每个回调存储已关闭相同的变量i
并且在循环完成后该变量的值为2
。
换句话说, 闭包在变量本身上,而不是在创建闭包时的值 。 正如其他人所说,使用包含i
作为参数的包装函数可以很容易地解决这个问题。 这会为每个要关闭的回调创建一个新变量。
这是一个人为的例子:
var someObj = {
callbacks: [],
myMethod: function(person, callback) {
someObj.callbacks.push(callback);
}
}
var Person = [['John', 0, 0, 0],['Chris', 1, 0, 0]];
for (i = 0; i < Person.length; i++ )
{
(function(i) {
someObj.myMethod(Person[i][0], function (object) {
console.log(i);
});
})(i);
}
someObj.callbacks[0]();
someObj.callbacks[1]();
在您的情况下,另一个选项是将Person
的元素传递给您的回调,而不是它们在数组中的索引。
处理闭包问题的另一种方法是创建局部变量并将其传递给函数。
var Person = [['John', 0, 0, 0],['Chris', 1, 0, 0]];
for (var i = 0; i < Person.length; i++ ) {
var x = i;
someObj.myMethod(Person[x][0], function (object) {
console.log(Person[x][1]);
console.log(Person[x][2]);
console.log(Person[x][3]);
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.