如何在循环的方法调用中动态分配参数?

时间:2014-07-08 15:39:25

标签: javascript

遇到一个奇怪的问题,或许最好用代码解释:

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

不太确定如何克服这种行为?

我编码错了吗?或者我应该使用不同的模式? (鉴于我希望“消费”功能可用于我所有的水果等)

非常感谢!

3 个答案:

答案 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 :(得分: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
  }
}

答案 2 :(得分:-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);