2014-07-08 36 views
0

碰上一個奇怪的問題,通過代碼也許最好的解釋:如何從循環中動態地分配方法調用中的參數?

var fruits = ["apples", "oranges", "pears"]; 

var Breakfast = { 
    _consume : function (fruit) { 
    Breakfast[fruit]._numConsumed++; 
    } 
}; 

for (var f in fruits) { 
    var fruit = fruits[f]; 
    Breakfast[fruit] = { 
    consume : function() { 
     Breakfast._consume(fruit); 
    }, 
    _numConsumed: 0 
    } 
} 

Breakfast.pears.consume(); 
Breakfast.pears.consume(); 

Breakfast.apples.consume(); 
Breakfast.apples.consume(); 
Breakfast.apples.consume(); 


console.log("Pears eaten: " + Breakfast.pears._numConsumed); 
console.log("Apples eaten: " + Breakfast.apples._numConsumed); 

這樣做的結果是:

$ node example.js 
Pears eaten: 5 
Apples eaten: 0 

不太清楚如何克服這種行爲?

我編碼有問題嗎?或者我應該使用不同的模式? (因爲我想要「消費」功能可用於我所有的水果等)

非常感謝!

+0

你'fruit'沒有上鎖,由你來調用'Breakfast.apples.consume()'變量水果設爲'pear'的時間,所以它要求你的通用早餐方法使用梨作爲它更新的水果。 – scragar

回答

0

的問題是,您的變量將永遠是最後的for循環。一個更簡單的方法是隻在你創建的對象中定義屬性。

var fruits = ["apples", "oranges", "pears"]; 

var Breakfast = { 
    _consume : function (fruit) { 
    Breakfast[fruit]._numConsumed++; 
    } 
}; 

for (var f in fruits) { 
    var fruit = fruits[f]; 
    Breakfast[fruit] = { 
    id:fruit, 
    consume : function() { 
     Breakfast._consume(this.id); 
    }, 
    _numConsumed: 0 
    } 
} 
0

你已經遇到了函數閉包的麻煩。有一個在這個問題一個很好的解釋:How do JavaScript closures work?

你的情況的問題是,這條線:

Breakfast._consume(fruit); 

總是會等同於

Breakfast._consume(fruits[2]); 

一旦你for循環結束運行。

可以通過給整個循環自己的上下文每個f解決它:

for (var f in fruits) { 
    (function(f) { 
    var fruit = fruits[f]; 
    Breakfast[fruit] = { 
    consume : function() { 
     Breakfast._consume(fruit); 
    }, 
    _numConsumed: 0 
    } 
    })(f); 
} 

...會導致...

"Pears eaten: 2" 
"Apples eaten: 3" 

但是,這是一個相當原油溶液。一旦你閱讀了關於函數閉包如何工作的解釋,我相信你會想出更好的方法。

-1

編輯答案:

var fruits = ["apples", "oranges", "pears"]; 

var Breakfast = { 
    _consume : function (fruit) { 
    console.log('other'+JSON.stringify(fruit)); 
    Breakfast[fruit]._numConsumed++; 
    } 
}; 

for (var f in fruits) { 
    //var fruit = fruits[f]; 
    Breakfast[fruits[f]] = { 
    fruit: fruits[f], 
    consume : function() { 
     Breakfast._consume(this.fruit); 
    }, 
    _numConsumed: 0 
    } 
} 

Breakfast.pears.consume(); 
Breakfast.pears.consume(); 

Breakfast.apples.consume(); 
Breakfast.apples.consume(); 
Breakfast.apples.consume(); 


console.log("Pears eaten: " + Breakfast.pears._numConsumed); 
console.log("Apples eaten: " + Breakfast.apples._numConsumed); 
+0

不確定這是否是所需的行爲 - 因爲您必須通過我們試圖避免的參數 – mark

+0

修復它,以便您不必使用aparam,而是我們將使用this.fruit –

相關問題