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

How to dynamically assign arguments in a method call from loop?

本文关键字:方法 动态分配 参数 调用 循环      更新时间:2023-09-26

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

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

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

我写错了什么吗?还是我应该用另一种模式?(假设我想让"消费"函数对我所有的水果都可用)

多谢!

问题是变量总是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
  }
}

您在使用函数闭包时遇到了一些麻烦。这个问题有一个很好的解释:JavaScript闭包是如何工作的?

你的问题是这一行:

  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"

但这是一个相当粗糙的解决方案。我相信,一旦您通读了函数闭包如何工作的解释,您就会想出更好的方法。

编辑回答:

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);