Every function scope in JavaScript can access the special variable arguments.
This variable holds a list of all the arguments that were passed to the function.
Note: In case
argumentshas already been defined inside the function's scope either via avarstatement or being the name of a formal parameter, theargumentsobject will not be created.
The arguments object is not an Array. While it has some of the
semantics of an array - namely the length property - it does not inherit from
Array.prototype and is in fact an Object.
Due to this, it is not possible to use standard array methods like push,
pop or slice on arguments. While iteration with a plain for loop works
just fine, it is necessary to convert it to a real Array in order to use the
standard Array methods on it.
The code below will return a new Array containing all the elements of the
arguments object.
Array.prototype.slice.call(arguments);
Because this conversion is slow, it is not recommended to use it in performance-critical sections of code.
The following is the recommended way of passing arguments from one function to another.
function foo() {
bar.apply(null, arguments);
}
function bar(a, b, c) {
// do stuff here
}
Another trick is to use both call and apply together to create fast, unbound
wrappers.
function Foo() {}
Foo.prototype.method = function(a, b, c) {
console.log(this, a, b, c);
};
// Create an unbound version of "method"
// It takes the parameters: this, arg1, arg2...argN
Foo.method = function() {
// Result: Foo.prototype.method.call(this, arg1, arg2... argN)
Function.call.apply(Foo.prototype.method, arguments);
};
The arguments object creates getter and setter functions for both its
properties, as well as the function's formal parameters.
As a result, changing the value of a formal parameter will also change the value
of the corresponding property on the arguments object, and the other way around.
function foo(a, b, c) {
arguments[0] = 2;
a; // 2
b = 4;
arguments[1]; // 4
var d = c;
d = 9;
c; // 3
}
foo(1, 2, 3);
The arguments object is always created with the only two exceptions being the
cases where it is declared as a name inside of a function or one of its formal
parameters. It does not matter whether it is used or not.
Both getters and setters are always created; thus, using it has nearly
no performance impact at all, especially not in real world code where there is
more than a simple access to the arguments object's properties.
ES5 Note: These getters and setters are not created in strict mode.
However, there is one case which will drastically reduce the performance in
modern JavaScript engines. That case is the use of arguments.callee.
function foo() {
arguments.callee; // do something with this function object
arguments.callee.caller; // and the calling function object
}
function bigLoop() {
for(var i = 0; i < 100000; i++) {
foo(); // Would normally be inlined...
}
}
In the above code, foo can no longer be a subject to inlining since it
needs to know about both itself and its caller. This not only defeats possible
performance gains that would arise from inlining, but it also breaks encapsulation
because the function may now be dependent on a specific calling context.
It is highly recommended to never make use of arguments.callee or any of
its properties.
ES5 Note: In strict mode,
arguments.calleewill throw aTypeErrorsince its use has been deprecated.