270

Is it possible to convert an array in JavaScript into a function argument sequence? Example:

run({ "render": [ 10, 20, 200, 200 ] });

function run(calls) {
  var app = .... // app is retrieved from storage
  for (func in calls) {
    // What should happen in the next line?
    var args = ....(calls[func]);
    app[func](args);  // This is equivalent to app.render(10, 20, 200, 200);
  }
}
TylerH
  • 20,799
  • 66
  • 75
  • 101
dpq
  • 9,028
  • 10
  • 49
  • 69
  • 3
    Check for a similar question also here: http://stackoverflow.com/questions/2856059/passing-an-array-as-a-function-parameter-in-javascript – Wilt Feb 25 '14 at 11:14
  • 4
    I guess it doesn't matter, but it seems odd that this older question is the one marked as the duplicate of the newer, referenced question? – shuckster Jun 13 '17 at 15:29

5 Answers5

333

Yes. In current versions of JS you can use:

app[func]( ...args );

Users of ES5 and older will need to use the .apply() method:

app[func].apply( this, args );

Read up on these methods at MDN:

shuckster
  • 5,279
  • 2
  • 23
  • 22
  • window does not seem to be necessary. – JBCP Sep 24 '14 at 21:52
  • This doesn't work if you want to call a function within an object – e.g. the following doesn't work: `window.document.execCommand.apply(window,["insertHorizontalRule",false])` – adib Oct 03 '15 at 08:10
  • That's because, in your case, you should specify `window.document` as the first argument, not just `window`: `window.document.execCommand.apply(window.document, ... )` – shuckster Oct 16 '15 at 14:36
  • 1
    `window` actually makes no sense in non-browser JavaScript frameworks such as NodeJS, therefore I'd suggest removing it from the answer. – zbr Dec 14 '15 at 15:31
  • 4
    If you can use ES6 features you can even use `f(...[1,2,3])`. – manixx Jan 19 '17 at 10:43
  • Another good idea. Done! – shuckster Jan 24 '17 at 11:44
126

A very readable example from another post on similar topic:

var args = [ 'p0', 'p1', 'p2' ];

function call_me (param0, param1, param2 ) {
    // ...
}

// Calling the function using the array with apply()
call_me.apply(this, args);

And here a link to the original post that I personally liked for its readability

Wilt
  • 41,477
  • 12
  • 152
  • 203
  • If that works, why won't this work? `document.body.setAttribute.apply( this, ["foo", "bar"] );` I need to send variable arguments to various object methods with different argument requirements. _Quick edit: Apparently `this` has to be document.body, or whatever the parent is_ – bryc Feb 25 '15 at 06:17
  • On a Typescript constructor this will raise an error: `Only a void function can be called with the 'new' keyword` – Augie Gardner Oct 22 '16 at 02:55
25
app[func].apply(this, args);
Eric Anderson
  • 918
  • 8
  • 9
12

You might want to take a look at a similar question posted on Stack Overflow. It uses the .apply() method to accomplish this.

Community
  • 1
  • 1
JJ Geewax
  • 10,342
  • 1
  • 37
  • 49
1

@bryc - yes, you could do it like this:

Element.prototype.setAttribute.apply(document.body,["foo","bar"])

But that seems like a lot of work and obfuscation compared to:

document.body.setAttribute("foo","bar")
user1527225
  • 1,059
  • 9
  • 7