363

I'd like to call a function using an array as parameters:

const x = ['p0', 'p1', 'p2'];
call_me(x[0], x[1], x[2]); // I don't like it

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

Is there a better way of passing the contents of x into call_me()?

Robert
  • 4,324
  • 2
  • 18
  • 22

12 Answers12

494
const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);

See MDN docs for Function.prototype.apply().


If the environment supports ECMAScript 6, you can use a spread argument instead:

call_me(...args);
Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
KaptajnKold
  • 10,638
  • 10
  • 41
  • 56
  • 10
    As a side note, if anyone wants to pass an associative array (named keys) instead, then use an object. Coming from PHP (and always led to this thread by google) this took me a while to figure out. You can pass the whole object as a parameter then. http://www.w3schools.com/js/js_objects.asp – timhc22 May 29 '14 at 08:56
  • Thanks for pointing out the 'spread' argument! Didn't know about it. – Thomas An Nov 12 '17 at 21:44
  • @timhc - your side note comment is intriguing, but I can't parse it (I'm a javascript noob working thru a couple of tutorials). In JS, an associative array _is_ an object according to several tutorials. – NateT Aug 28 '18 at 14:15
  • @timhc22 , and when using the json object to pass as a parameter to a function dont forget the [Parameter Destruction](https://2ality.com/2015/01/es6-destructuring.html) for better readability – Muhammad Omer Aslam Sep 05 '19 at 13:50
  • Never thought I would use it one day, now the day has come to use spread arguments. – Timo Jul 24 '22 at 20:15
145

Why don't you pass the entire array and process it as needed inside the function?

var x = [ 'p0', 'p1', 'p2' ]; 
call_me(x);

function call_me(params) {
  for (i=0; i<params.length; i++) {
    alert(params[i])
  }
}
Karl Johan
  • 4,012
  • 1
  • 25
  • 36
  • 41
    It's because i can't modify call_me(). It is defined in some other library and it is not possible to mess with the API. – Robert May 18 '10 at 11:54
  • 81
    +1 because even though it doesn't answer the original question, it's probably what the 100K+ people who viewed this page were looking for. – Ishikawa Mar 05 '15 at 00:21
  • Can someone explain what the "call_me(x)" line is doing? It seems as it is a function name without the function keyword? What exactly is it doing? – swam Nov 20 '15 at 06:19
  • 1
    @swam It is a call to the `call_me` function. It just lacks a semicolon at the end. – SantiBailors Dec 16 '15 at 16:04
  • @swam it is putting in execution the declared call_me(params) function. – Julio Rodriguez Oct 23 '18 at 20:42
67

In ES6 standard there is a new spread operator ... which does exactly that.

call_me(...x)

It is supported by all major browsers except for IE.

The spread operator can do many other useful things, and the linked documentation does a really good job at showing that.

zenofpython
  • 182
  • 1
  • 2
  • 14
BoltKey
  • 1,994
  • 1
  • 14
  • 26
46

Assuming that call_me is a global function, so you don't expect this to be set.

var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);
plexer
  • 4,542
  • 2
  • 23
  • 27
8

As @KaptajnKold had answered

var x = [ 'p0', 'p1', 'p2' ];
call_me.apply(this, x);

And you don't need to define every parameters for call_me function either. You can just use arguments

function call_me () {
    // arguments is a array consisting of params.
    // arguments[0] == 'p0',
    // arguments[1] == 'p1',
    // arguments[2] == 'p2'
}
徐竟峰
  • 147
  • 2
  • 3
  • 4
    This is such bad practice... you wont be able to see what the function needs and every parameters is optional if you look at the function. – Robin Oct 31 '16 at 08:06
7

While using spread operator we must note that it must be the last or only parameter passed. Else it will fail.

function callMe(...arr){ //valid arguments
    alert(arr);
}

function callMe(name, ...arr){ //valid arguments
    alert(arr);
}

function callMe(...arr, name){ //invalid arguments
    alert(arr);
}

If you need to pass an array as the starting argument you can do:

function callMe(arr, name){
    let newArr = [...arr];
    alert(newArr);
}
Naba
  • 124
  • 1
  • 5
5

Function arguments may also be Arrays:

function foo([a,b,c], d){
  console.log(a,b,c,d);
}

foo([1,2,3], 4)

of-course one can also use spread:

function foo(a, b, c, d){
  console.log(a, b, c, d);
}

foo(...[1, 2, 3], 4)
Community
  • 1
  • 1
vsync
  • 118,978
  • 58
  • 307
  • 400
4

Note this

function FollowMouse() {
    for(var i=0; i< arguments.length; i++) {
        arguments[i].style.top = event.clientY+"px";
        arguments[i].style.left = event.clientX+"px";
    }

};

//---------------------------

html page

<body onmousemove="FollowMouse(d1,d2,d3)">

<p><div id="d1" style="position: absolute;">Follow1</div></p>
<div id="d2" style="position: absolute;"><p>Follow2</p></div>
<div id="d3" style="position: absolute;"><p>Follow3</p></div>


</body>

can call function with any Args

<body onmousemove="FollowMouse(d1,d2)">

or

<body onmousemove="FollowMouse(d1)">
Alejandro Silva
  • 8,808
  • 1
  • 35
  • 29
ali.b.y
  • 67
  • 2
  • This is clearly part of the answer. "arguments" is definitely needed to get the array back after the call. Thanks! – FlorianB Jun 25 '16 at 14:30
3

you can use the spread syntax

for example:

function print(...inpu){
console.log(...inpu)
}
var arry = ['p0','p1','p2']
print(...arry)
here is the link: modzilla spread syntax refrence document
  • 1
    That is technically the same answer that BoltKey wrote 1,5 years before you wrote this – Harry May 09 '22 at 09:53
1

you can use spread operator in a more basic form

[].concat(...array)

in the case of functions that return arrays but are expected to pass as arguments

Example:

function expectArguments(...args){
  return [].concat(...args);
}

JSON.stringify(expectArguments(1,2,3)) === JSON.stringify(expectArguments([1,2,3]))

rman
  • 135
  • 1
  • 7
0

The answer was already given, but I just want to give my piece of cake. What you want to achieve is called method borrowing in the context of JS, that when we take a method from an object and call it in the context of another object. It is quite common to take array methods and apply them to arguments. Let me give you an example.

So we have "super" hashing function which takes two numbers as an argument and returns "super safe" hashed string:

function hash() {
  return arguments[0]+','+arguments[1];
}

hash(1,2); // "1,2" whoaa

So far so good, but we have little problem with the above approach, it is constrained, only works with two numbers, that is not dynamic, let's make it work with any number and plus you do not have to pass an array (you can if you still insist). Ok, Enough talk, Let's fight!

The natural solution would be to use arr.join method:

function hash() {
  return arguments.join();
}

hash(1,2,4,..); //  Error: arguments.join is not a function

Oh, man. Unfortunately, that won’t work. Because we are calling hash(arguments) and arguments object is both iterable and array-like, but not a real array. How about the below approach?

function hash() {
  return [].join.call(arguments);
}

hash(1,2,3,4); // "1,2,3,4" whoaa

The trick is called method borrowing.

We borrow a join method from a regular array [].join. And use [].join.call to run it in the context of arguments.

Why does it work?

That’s because the internal algorithm of the native method arr.join(glue) is very simple.

Taken from the specification almost “as-is”:

Let glue be the first argument or, if no arguments, then a comma ",".
Let result be an empty string.
Append this[0] to result.
Append glue and this[1].
Append glue and this[2].
…Do so until this.length items are glued.
Return result.

So, technically it takes this and joins this[0], this[1] …etc together. It’s intentionally written in a way that allows any array-like this (not a coincidence, many methods follow this practice). That’s why it also works with this=arguments.

Humoyun Ahmad
  • 2,875
  • 4
  • 28
  • 46
-1

There's a better way using JSON not an Array!

   // Call a function with a Json Key / Value Pair:
   sendMail({param1: p1, param2: p2});

   // Function definition and usage of value pairs:
   function sendMail(data){
     var parameter1 = data.param1;
     var parameter2 = data.param2;
   }
gtamborero
  • 2,898
  • 27
  • 28