2

有没有办法在javascript中进行以下工作?

var orders = [
   {milk: true, sugar: "extra"}, 
   {milk: false, sugar: "normal"}
   ];

function makeCoffee(sugar, milk) {
    console.log(sugar);
    console.log(milk);
}

orders.forEach(makeCoffee);
4

3 回答 3

2

正如我在评论中所说,在func.toString()返回函数†</sup> 源的浏览器中,您可以解析签名并提取参数名称:

var arg_names = makeCoffee.toString()
            .match(/function[^(]*\(([^)]*)\)/)[1].split(', ');

orders.each(function(order) {
    makeCoffee.apply(null, arg_names.map(function(name) {
        return order[name];
    });
});

由于 JavaScript 不提供任何反射 API,这可能是唯一的方法。


如果您没有明确说明您的代码在哪些浏览器中受支持,这可能不起作用(我不知道 IE 返回什么func.toString)。我仍然建议将对象作为参数传递。


†:函数的确切表示取决于实现。以下是规范中的相应描述:

返回函数的依赖于实现的表示。此表示具有 a 的语法FunctionDeclaration。请特别注意,在表示字符串中使用和放置空格、行终止符和分号是依赖于实现的。

于 2012-07-31T09:29:38.283 回答
0

到目前为止,我能想到的最好的是:

function makeCoffee() {
    console.log(this.milk);
    console.log(this.sugar);
}

orders.forEach(function(x) {makeCoffee.call(x)})

优点:

  • 作品

缺点(海事组织):

  • 它在 order 和 makeCoffee 之间引入了不必要的耦合(有点像组合与继承之间的关系)。
  • 我们失去了声明其输入的 makeCoffee 函数的明确性
于 2012-07-31T09:13:32.080 回答
0

我推荐这个:

//Should go to config.js
var COFFEE_SUGAR_DEFAULT="normal";

var orders = [
   {milk: true, sugar: "extra"}, 
   {milk: false, sugar: "normal"}
   ];

function makeCoffee(coffeeDefinition) {
    if (!coffeeDefinition.sugar) coffeeDefinition.sugar=COFFEE_SUGAR_DEFAULT;
    if (!coffeeDefinition.milk) coffeeDefinition.milk=false; //might not be a real boolean
    console.log(coffeeDefinition.sugar);
    console.log(coffeeDefinition.milk);
}

orders.forEach(function(x) {makeCoffee(x)})

优点:

  • 工作并且很健壮
  • 只引入了必要的耦合
  • 可扩展到例如"decaffeinated":false

缺点:

  • 不漂亮
于 2012-07-31T09:24:11.503 回答