265

In PHP there is func_num_args and func_get_args, is there something similar for JavaScript?

Ethan
  • 4,295
  • 4
  • 25
  • 44
rsk82
  • 28,217
  • 50
  • 150
  • 240

12 Answers12

396

For modern Javascript or Typescript:

class Foo {
    reallyCoolMethodISwear(...args) { return args.length; }
}

function reallyCoolFunction(i, ...args) { return args[i]; }

const allHailTheLambda = (...args) => {
    return args.constructor == Array;
};

const x = new Foo().reallyCoolMethodISwear(0, 1, 2, 3, 4);
const y = reallyCoolFunction(3, 0, 1, 2, 3, 4, 5, 6);
const z = allHailTheLambda(43110, "world");

console.log(x, y, z); // 5 3 true

For ancient Javascript:

Use arguments. You can access it like an array. Use arguments.length for the number of arguments.

Thomas Eding
  • 35,312
  • 13
  • 75
  • 106
  • 75
    This only works for the traditional JavaScript `function`, not ES2015+ fat arrow `=>` functions. For those, you'll wanna use `...args` in the function definition like so: `(...args) => console.log(args)`. – Kevin Ghadyani Jul 27 '17 at 19:33
  • "Uncaught ReferenceError: arguments is not defined" – David Spector Jun 26 '21 at 13:23
  • David: window.location is not set as expected when a JavaScript file is included in HTML using a SCRIPT tag. Any arguments are lost using this approach. – David Spector Jun 26 '21 at 15:20
164

The arguments is an array-like object (not an actual array). Example function...

function testArguments () // <-- notice no arguments specified
{
    console.log(arguments); // outputs the arguments to the console
    var htmlOutput = "";
    for (var i=0; i < arguments.length; i++) {
        htmlOutput += '<li>' + arguments[i] + '</li>';
    }
    document.write('<ul>' + htmlOutput + '</ul>');
}

Try it out...

testArguments("This", "is", "a", "test");  // outputs ["This","is","a","test"]
testArguments(1,2,3,4,5,6,7,8,9);          // outputs [1,2,3,4,5,6,7,8,9]

The full details: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments

Luke
  • 18,811
  • 16
  • 99
  • 115
  • 4
    Why not post the result here too? :) – Jonathan Jul 15 '13 at 18:17
  • 2
    This is much better than the accepted answer because it contains a working code snippet and shows output. The accepted answer is too sparse. – Mac Apr 18 '16 at 12:21
  • Good answer...would be a great answer with expanding on "not an actual array" – terpinmd Aug 07 '17 at 12:46
  • I added a link to a simple description: an "Array-like Object" is just an "Object which has a length property of a non-negative Integer, and usually some indexed properties." From the mozilla link: "It is similar to an Array, but does not have any Array properties except length." – Luke Aug 07 '17 at 13:09
56

ES6 allows a construct where a function argument is specified with a "..." notation such as

function testArgs (...args) {
 // Where you can test picking the first element
 console.log(args[0]); 
}
  • 4
    This seems to be the only way when using arrow function. `a = () => {console.log(arguments);}; a('foo');` gives `-- Uncaught ReferenceError: arguments is not defined` However `a = (...args) => {console.log(args);}; a('foo');` gives `["foo"]` – David Baucum Feb 24 '17 at 14:21
  • 2
    @DavidBaucum that is correct. Because arrow function does not create a new scope, and "arguments" is collected from the scope. But the worst case scenario isn't a ReferenceError. It is that "arguments" is collected from an outer scope. Then you get no exception, and maybe strange bugs in your application. – pgsandstrom May 18 '17 at 12:01
  • 3
    This is also called "rest parameters", see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters. – Dennis Apr 04 '18 at 15:45
23

The arguments object is where the functions arguments are stored.

The arguments object acts and looks like an array, it basically is, it just doesn't have the methods that arrays do, for example:

Array.forEach(callback[, thisArg]);

Array.map(callback[, thisArg])

Array.filter(callback[, thisArg]);

Array.slice(begin[, end])

Array.indexOf(searchElement[, fromIndex])

I think the best way to convert a arguments object to a real Array is like so:

argumentsArray = [].slice.apply(arguments);

That will make it an array;

reusable:

function ArgumentsToArray(args) {
    return [].slice.apply(args);
}

(function() {
   args = ArgumentsToArray(arguments);

   args.forEach(function(value) {
      console.log('value ===', value);
   });

})('name', 1, {}, 'two', 3)

result:

> value === name
> value === 1
> value === Object {}
> value === two
> value === 3

iConnor
  • 19,997
  • 14
  • 62
  • 97
11

You can also convert it to an array if you prefer. If Array generics are available:

var args = Array.slice(arguments)

Otherwise:

var args = Array.prototype.slice.call(arguments);

from Mozilla MDN:

You should not slice on arguments because it prevents optimizations in JavaScript engines (V8 for example).

wcr4
  • 55
  • 8
Iman Mohamadi
  • 6,552
  • 3
  • 34
  • 33
  • 2
    Thanks for the update. Use JSON.stringify and JSON.parse as an alternative:`function foo() { foo.bar = JSON.stringify(arguments); foo.baz = JSON.parse(foo.bar); }` If preservation is needed instead of stringification, use the [internal structured cloning algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm). If DOM nodes are passed, use XMLSerializer as in an [unrelated question](http://stackoverflow.com/questions/17273110/1113772). `with (new XMLSerializer()) {serializeToString(document.documentElement) }` – Paul Sweatte Apr 02 '15 at 16:58
8

As many other pointed out, arguments contains all the arguments passed to a function.

If you want to call another function with the same args, use apply

Example:

var is_debug = true;
var debug = function() {
  if (is_debug) {
    console.log.apply(console, arguments);
  }
}

debug("message", "another argument")
Lasse Skindstad Ebert
  • 3,370
  • 2
  • 29
  • 28
4

Similar answer to Gunnar, with more complete example: You can even transparently return the whole thing:

function dumpArguments(...args) {
  for (var i = 0; i < args.length; i++)
    console.log(args[i]);
  return args;
}

dumpArguments("foo", "bar", true, 42, ["yes", "no"], { 'banana': true });

Output:

foo
bar
true
42
["yes","no"]
{"banana":true}

https://codepen.io/fnocke/pen/mmoxOr?editors=0010

Frank N
  • 9,625
  • 4
  • 80
  • 110
3

Yes if you have no idea that how many arguments are possible at the time of function declaration then you can declare the function with no parameters and can access all variables by arguments array which are passed at the time of function calling.

Rubi saini
  • 2,515
  • 23
  • 21
3

In ES6 you can do something like this:

function foo(...args) 
{
   let [a,b,...c] = args;

   console.log(a,b,c);
}


foo(1, null,"x",true, undefined);
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
0

Hope this helps:

function x(...args) {
    console.log( {...[...args] } ); 
}

x({a:1,b:2}, 'test');

Output:

{ '0': { a: 1, b: 2 }, '1': 'test' }
Vontei
  • 1,727
  • 2
  • 14
  • 16
0

Hope this could be the helpful code:

function lazyLoadIcons(){
    for(let i = 0; i < arguments.length; i++) {
        var elements = document.querySelectorAll(arguments[i]);
        elements.forEach(function(item){
            item.classList.add('loaded');
        });
    }
}

lazyLoadIcons('.simple-2col', '.ftr-blue-ad', '.btm-numb');  

~ Rahul Daksh

Rahul Daksh
  • 212
  • 1
  • 7
-11

In ES6, use Array.from:

function foo()
  {
  foo.bar = Array.from(arguments);
  foo.baz = foo.bar.join();
  }

foo(1,2,3,4,5,6,7);
foo.bar // Array [1, 2, 3, 4, 5, 6, 7]
foo.baz // "1,2,3,4,5,6,7"

For non-ES6 code, use JSON.stringify and JSON.parse:

function foo()
  {
  foo.bar = JSON.stringify(arguments); 
  foo.baz = JSON.parse(foo.bar); 
  }

/* Atomic Data */
foo(1,2,3,4,5,6,7);
foo.bar // "{"0":1,"1":2,"2":3,"3":4,"4":5,"5":6,"6":7}"
foo.baz // [object Object]

/* Structured Data */
foo({1:2},[3,4],/5,6/,Date())
foo.bar //"{"0":{"1":2},"1":[3,4],"2":{},"3":"Tue Dec 17 2013 16:25:44 GMT-0800 (Pacific Standard Time)"}"
foo.baz // [object Object]

If preservation is needed instead of stringification, use the internal structured cloning algorithm.

If DOM nodes are passed, use XMLSerializer as in an unrelated question.

with (new XMLSerializer()) {serializeToString(document.documentElement) }

If running as a bookmarklet, you may need to wrap the each structured data argument in an Error constructor for JSON.stringify to work properly.

References

Community
  • 1
  • 1
Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
  • 3
    First: this will clone whatever objects are passed in. Second: not everything can be stringified to JSON. Namely: functions, DOM objects, said dates stringify as strings... – John Dvorak Feb 15 '14 at 18:33
  • @JanDvorak Can you edit my answer with a function that handles DOM objects, functions, and dates? – Paul Sweatte Feb 18 '14 at 17:46
  • 1
    +1, trying to pass the arguments for error reporting as a string, the object ends up as a string '[object Arguments]' and logging that to the console doesn't display the values. While it doesn't seem to answer the OP it does answer my question, thanks! – John Jun 07 '14 at 18:49