104

Is there a way to pass an unknown number of arguments like:

var print_names = function(names) {
    foreach(name in names) console.log(name); // something like this
}

print_names('foo', 'bar', 'baz');

Also, how do I get the number of arguments passed in?

2

13 Answers 13

181

ES3 (or ES5 or oldschool JavaScript)

You can access the arguments passed to any JavaScript function via the magic arguments object, which behaves similarly to an array. Using arguments your function would look like:

var print_names = function() {
     for (var i=0; i<arguments.length; i++) console.log(arguments[i]);
}

It's important to note that arguments is not an array. MDC has some good documentation on it: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#Using_the_arguments_object

If you want to turn arguments into an array so that you can do things like .slice(), .push() etc, use something like this:

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

ES6 / Typescript

There's a better way! The new rest parameters feature has your back:

var print_names = function(...names) {
    for (let i=0; i<names.length; i++) console.log(names[i]);
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for such a detailed and at the same time short+simple answer :)
Thanks for your answer! I found this to be a helpful article explaining what's happening with Array.prototype.slice.call(arguments): medium.com/@andrewsburke/…
How would you properly type the ...names
29

ES6/ES2015

Take advantage of the rest parameter syntax.

function printNames(...names) {
  console.log(`number of arguments: ${names.length}`);
  for (var name of names) {
    console.log(name);
  }
}

printNames('foo', 'bar', 'baz');

There are three main differences between rest parameters and the arguments object:

  • rest parameters are only the ones that haven't been given a separate name, while the arguments object contains all arguments passed to the function;
  • the arguments object is not a real array, while rest parameters are Array instances, meaning methods like sort, map, forEach or pop can be applied on it directly;
  • the arguments object has additional functionality specific to itself (like the callee property).

2 Comments

This makes perfect sense for web development that usually uses common PHP syntax.
Though (even more important in 2016 when the answer went up), recall that there's no Internet Explorer support for spreads if you're not transpiling. Key gotcha I've seen too often: Devs use stuff like this in templates, which often aren't transpiled even when their TypeScript (typically) is.
14
var 
print_names = function() {
    console.log.apply( this, arguments );
};

print_names( 1, 2, 3, 4 );

Comments

7
function print_args() {
    for(var i=0; i<arguments.length; i++)
        console.log(arguments[i])
}

Comments

6

There is a hidden object passed to every function in JavaScript called arguments.

You would just use arguments.length to get the amount of arguments passed to the function.

To iterate through the arguments, you would use a loop:

for(var i = arguments.length; i--) {
   var arg = arguments[i];
}

Note that arguments isn't a real array, so if you needed it as an array you would convert it like this:

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

1 Comment

Just note that it isn't a "real" array, it is an "array-like" object (with some special characteristics), but to use "Array methods" on it, you will need to convert it, e.g. var args = Array.prototype.slice.call(arguments);, var args = Array.apply(null, arguments);, etc, there are many ways...
4

arguments.length. you can use a for loop on it.

(function () {
    for (var a = [], i = arguments.length; i--;) {
        a.push(arguments[i]);
    };
    return a;
})(1, 2, 3, 4, 5, 6, 7, 8)

9 Comments

@meder, I love using anonymous functions like that. Nice example! Also, are you missing a couple of semicolons there?
@meder, Semicolon insertion in JavaScript #ftf
@meder, indeed, just the semicolon after the for block is not really needed, however I would add one at the end of the last line.
Why do you have to put the function between ()?
@weng, it's about FunctionExpression vs FunctionDeclaration, check this article.
|
2

Much better now for ES6

function Example() {
    return {
        arguments: (...args) =>{
            args.map(a => console.log());
        }
    }
}

var exmpl = new Example();
exmpl.arguments(1, 2, 3, 'a', 'b', 'c');

I hope this helps

Comments

2

Rest parameters in ES6

const example = (...args) => {
  for (arg in args) {
    console.log(arg);
  }
}

Note: you can pass regular parameters in before the rest params

const example = (arg1, ...args) => {
  console.log(arg1);
  for (arg in args) {
    console.log(arg);
  }
}

Comments

0

You can use the spread/rest operator to collect your parameters into an array and then the length of the array will be the number of parameters you passed:

function foo(...names) {
    console.log(names);
    return names;
}

console.log(foo(1, 2, 3, 4).length);

Using BabelJS I converted the function to oldschool JS:

"use strict";

function foo() {
  for (var _len = arguments.length, names = new Array(_len), _key = 0; _key < _len; _key++) {
    names[_key] = arguments[_key];
  }

  console.log(names);
  return names;
}

Comments

0

You can create a function using the spread/rest operator and from there on, you achieved your goal. Please take a look at the chunk below.

const print_names = (...args) => args.forEach(x => console.log(x));

Comments

0

let x = function(){
  return [].slice.call(arguments);
};

console.log(x('a','b','c','d'));

Comments

0

Here is the best answer using spread operator :)

function sum(...nums)
{
    let total =0;
     for(num of nums)
     {
         total+=num;
     }
    console.log(total)
}
console.log(sum(2,4,5,6,7));

Comments

-4

I like to do this:

This will not help if you don't know the number of arguments, but it helps if you don't want to remember the order of them.

/**
 *  @param  params.one        A test parameter
 *  @param  params.two        Another one  
 **/
function test(params) {

    var one = params.one;
    if(typeof(one) == 'undefined') {
        throw new Error('params.one is undefined');
    }

    var two = params.two;
    if(typeof(two) == 'undefined') {
        throw new Error('params.two is undefined');
    }
}

1 Comment

The question was about unknown number of arguments.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.