foreach - Javascript explode object to arguments - Stack Overflow

admin2025-04-19  2

Is there some way to make the following work in javascript?

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

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

orders.forEach(makeCoffee);

Is there some way to make the following work in javascript?

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

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

orders.forEach(makeCoffee);
Share Improve this question asked Jul 31, 2012 at 9:13 ManavManav 10.4k7 gold badges46 silver badges52 bronze badges 4
  • They easiest way would to make makeCoffee accept a single object with the arguments. Since object properties are unordered the only way to pass the properties in the right order is to parse the function signature and extract the parameter names. I don't think that's worth it. – Felix Kling Commented Jul 31, 2012 at 9:16
  • @FelixKling that is exactly what I am trying to avoid – Manav Commented Jul 31, 2012 at 9:16
  • But it really is more flexible and relatively mon to do so, why are you trying to avoid it? – Felix Kling Commented Jul 31, 2012 at 9:17
  • @FelixKling it works, but it litters the code i.e. function makeCoffee(dummy) {console.log(dummy.milk); console.log(dummy.sugar);}. Anyways, the question is about if or not something like this is possible - debate about their pros and cons is for another day :) – Manav Commented Jul 31, 2012 at 9:19
Add a ment  | 

3 Answers 3

Reset to default 2

As I said in my ment, in browsers where func.toString() returns the source of the function , you could parse the signature and extract the parameter names:

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

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

Since JavaScript does not provide any reflection API, this is probably the only way.


If you don't explicitly state in which browsers your code is supported, this might not work (I don't know what IE returns for func.toString). I still remend to pass an object as argument.


†: The exact representation of the function is implementation dependent though. Here is the corresponding description from the specification:

An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration. Note in particular that the use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent.

The best I can e up with till now is:

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

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

Pros:

  • Works

Cons (IMO):

  • it introduces unnecessary coupling between the order and makeCoffee (sort of like how the position vs inheritance thing panned out).
  • we lose the explicitness of the makeCoffee function declaring its inputs

I remend this:

//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)})

pros:

  • works and is robust
  • introduces just the necessary coupling
  • is expandable to e.g. "decaffeinated":false

cons:

  • not pretty
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745063099a282818.html

最新回复(0)