javascript functions and arguments object, is there a cost involved

No one's done testing on this in a while, and all the links are dead. Here's some fresh results:

  var res = []
  for(var i = 0, l = arguments.length; i < l; i++){
    res.push(arguments[i])
  }
}

function loop_variable(){
  var res = []
  var args = arguments
  for(var i = 0, l = args.length; i < l; i++){
    res.push(args[i])
  }
  return res
}

function slice(){
    return Array.prototype.slice.call(arguments);
}

function spread(){
    return [...arguments];
}

function do_return(){
    return arguments;
}

function literal_spread(){
    return [arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9]];
}

function spread_args(...args){
  return args;
}

I tested these here: https://jsben.ch/bB11y, as do_return(0,1,2,3,4,5,6,7,8,9) and so on. Here are my results on my Ryzen 2700X, on Linux 5.13:

Firefox 90.0 Chromium 92.0
do_return 89% 100%
loop_variable 74% 77%
spread 63% 29%
loop 73% 94%
literal_spread 86% 100%
slice 68% 81%
spread_args 100% 98%

Here's some q&d testing. Using predefined arguments seems to be the fastest, but it's not always feasible to do this. If the arity of the function is unknown beforehand (so, if a function can or must receive a variable amount of arguments), I think calling Array.prototype.slice once would be the most efficient way, because in that case the performance loss of using the arguments object is the most minimal.


The arguments has two problems: one is that it's not a real array. The second one is that it can only include all of the arguments, including the ones that were explicitly declared. So for example:

function f(x, y) {
    // arguments also include x and y
}

This is probably the most common problem, that you want to have the rest of the arguments, without the ones that you already have in x and y, so you would like to have something like that:

var rest = arguments.slice(2);

but you can't because it doesn't have the slice method, so you have to apply the Array.prototype.slice manually.

I must say that I haven't seen converting all of the arguments to a real array just for the sake of performance, only as a convenience to call Array methods. I'd have to do some profiling to know what is actually faster, and it may also depend faster for what, but my guess would be that there's not much of a difference if you don't want to call the Array methods in which case you have no choice but to convert it to a real array or apply the methods manually using call or apply.

The good news is that in new versions of ECMAScript (Harmony?) we'll be able to write just this:

function f(x, y, ...rest) {
   // ...
}

and we'll be able to forget all of those ugly workarounds.