I never use variadic arguments in JavaScript. There are many better ways of structuring your code. For example, I would rewrite your code as follows:
[1,2,3,4,5].forEach(log); // instead of manyArgs(1,2,3,4,5);
function log(a) {
console.log(a);
}
It's clear and concise.
Another example, if you want to find the sum of a list of numbers in JavaScript:
[1,2,3,4,5].reduce(add, 0); // instead of add(1,2,3,4,5);
function add(a, b) {
return a + b;
}
There are so many useful abstractions available to structure your code that I don't see the benefit of using variadic arguments at all.
I do however use the arguments
object for default values:
function foo(a,b,c) {
switch (arguments.length) {
case 0: a = "default argument for a";
case 1: b = "default argument for b";
case 2: c = "default argument for c";
}
// do something with a, b & c
}
Hence my advise to you would be to not use variadic arguments at all. Find a better abstraction for your code. I've never encountered the need to use variadic arguments in the 8 years that I have been programming in JavaScript.
Edit: I would advocate using a more functional approach to writing code. We can use currying to make code more succinct:
function curry(func, length, args) {
switch (arguments.length) {
case 1: length = func.length;
case 2: args = [];
}
var slice = args.slice;
return function () {
var len = arguments.length;
var a = args.concat(slice.call(arguments));
if (len >= length) return func.apply(this, a);
return curry(func, length - len, a);
};
}
Using curry
we can rewrite the sum example as follows:
var reduce = curry(function (func, acc, a) {
var index = 0, length = a.length;
while (index < length) acc = func(acc, a[index++]);
return acc;
});
var sum = reduce(add, 0);
sum([1,2,3,4,5]); // instead of add(1,2,3,4,5);
function add(a, b) {
return a + b;
}
Similarly for Math.max
and Array.prototype.concat
:
var reduce1 = curry(function (func, a) {
if (a.length === 0)
throw new Error("Reducing empty array.");
return reduce(func, a[0], a.slice(1));
});
var maximum = reduce1(max);
maximum([1,2,3,4,5]); // instead of Math.max(1,2,3,4,5);
function max(a, b) {
return a > b ? a : b;
}
var concat = reduce(function (a, b) {
return a.concat(b);
}, []);
concat([[1,2],[3,4],[5,6]]) // instead of [1,2].concat([3,4],[5,6])
As for Array.prototype.push
, because it mutates the input array instead of creating a new one, I prefer using array.concat([element])
instead of array.push(element)
:
var push = reduce(function (a, e) {
return a.concat([e]);
});
push([1,2,3], [4,5]); // instead of [1,2,3].push(4, 5)
So what are the advantages of writing code this way:
- Currying is awesome. It allows you to create new functions from old ones.
- Instead of using variadic arguments you are passing arrays to functions. So you don't need any special way to indicate that the function uses
arguments
.
- Suppose you have to find the sum of an array named
array
. Using this method you just do sum(array)
. If you use variadic arguments then you would need to do add.apply(null, array)
.
- Suppose you want to find the sum of
a
, b
& c
. All you need to do is sum([a,b,c])
, as compared to add(a, b, c)
. You need to put in the extra []
brackets. However doing so makes your code more understandable. According to the zen of python “explicit is better than implicit”.
So these are some of the reasons I never use variadic arguments in my programs.