[英]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.