443

I've tried the following with no success:

function a(args){
    b(arguments);
}

function b(args){
    // arguments are lost?
}

a(1,2,3);

In function a, I can use the arguments keyword to access an array of arguments, in function b these are lost. Is there a way of passing arguments to another javascript function like I try to do?

Anders Nygaard
  • 5,433
  • 2
  • 21
  • 30
  • 3
    @BobStein-VisiBone Agreed. Plus, note that `arguments` is not *actually* an array (but rather an [object that implements array-like semantics](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments)) and therefore it is not entirely clear at first glance whether it can be used in the same way as an actual array can. – Jules Nov 27 '17 at 01:58
  • @Jules still **vote to reopen** after all these years. What's the badge for burninating other people's valuable work? A lot of those to go around. – Bob Stein Apr 24 '20 at 18:56

5 Answers5

582

Use .apply() to have the same access to arguments in function b, like this:

function a(){
    b.apply(null, arguments);
}
function b(){
    console.log(arguments); //arguments[0] = 1, etc
}
a(1,2,3);

You can test it out here.

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
312

Spread operator

The spread operator allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) are expected.

ECMAScript ES6 added a new operator that lets you do this in a more practical way: ...Spread Operator.

Example without using the apply method:

function a(...args){
  b(...args);
  b(6, ...args, 8) // You can even add more elements
}
function b(){
  console.log(arguments)
}

a(1, 2, 3)

Note This snippet returns a syntax error if your browser still uses ES5.

Editor's note: Since the snippet uses console.log(), you must open your browser's JS console to see the result - there will be no in-page result.

It will display this result:

Image of Spread operator arguments example

In short, the spread operator can be used for different purposes if you're using arrays, so it can also be used for function arguments, you can see a similar example explained in the official docs: Rest parameters

  • 7
    This is a very nice operator and I'm really looking forward to use it. However, it won't happen yet. The only browser that already supports spread operator is FF at the moment. See the compatibility table for a complete, up to date data: http://kangax.github.io/compat-table/es6/#spread_%28...%29_operator – TMG Aug 13 '15 at 08:37
  • 13
    Why shouldn't it be used? It's relatively easy to transpile with babel, you get all of the new features, and much more compatibility with older browsers. – adgelbfish Feb 16 '17 at 19:06
  • This is better than the first solution because it works in function defined with the arrow operator. – sarfata Jan 23 '19 at 08:14
  • You dont need `...args` in the `a` function. You can just make a function with no arguments and pass them on to `b` with `...arguments` – cronoklee Mar 18 '19 at 18:36
  • 1
    To anyone reading this answer: Contrary to @cronoklee's comment, explicitly specifying `...args` as `a`'s input can be important if you have nested functions. – Arshia001 May 26 '19 at 06:32
  • In TypeScript, you may get an error: "A spread argument must either have a tuple type or be passed to a rest parameter." To overcome this, use Parameters type as follows: ` function a(...args: Parameters) { b(...args); } ` Or for another common complex example: ` async function a(...args: Parameters) { return await b(...args); } ` – Marcus Apr 28 '23 at 22:03
84

The explanation that none of the other answers supplies is that the original arguments are still available, but not in the original position in the arguments object.

The arguments object contains one element for each actual parameter provided to the function. When you call a you supply three arguments: the numbers 1, 2, and, 3. So, arguments contains [1, 2, 3].

function a(args){
    console.log(arguments) // [1, 2, 3]
    b(arguments);
}

When you call b, however, you pass exactly one argument: a's arguments object. So arguments contains [[1, 2, 3]] (i.e. one element, which is a's arguments object, which has properties containing the original arguments to a).

function b(args){
    // arguments are lost?
    console.log(arguments) // [[1, 2, 3]]
}

a(1,2,3);

As @Nick demonstrated, you can use apply to provide a set arguments object in the call.

The following achieves the same result:

function a(args){
    b(arguments[0], arguments[1], arguments[2]); // three arguments
}

But apply is the correct solution in the general case.

alex
  • 479,566
  • 201
  • 878
  • 984
Wayne
  • 59,728
  • 15
  • 131
  • 126
3

If you want to only pass certain arguments, you can do so like this:

Foo.bar(TheClass, 'theMethod', 'arg1', 'arg2')

Foo.js

bar (obj, method, ...args) {
  obj[method](...args)
}

obj and method are used by the bar() method, while the rest of args are passed to the actual call.

dreamLo
  • 1,612
  • 12
  • 17
0

This one works like a charm.

function a(){
    b(...arguments);
}

function b(){
    for(var i=0;i<arguments.length;i++){
       //you can use arguments[i] here.
    }
}

a(1,2,3);
MrAlbino
  • 308
  • 2
  • 10