Cada ámbito de la función de JavaScript puede acceder a la variable especial arguments.
Está variable contiene una lista de todos los argumentos que se pasan a la función.
Nota: En este caso
argumentsya se ha definido dentro del ámbito de la función ya sea através de la sentenciavaro como un parámetro formal, el objetoargumentsno se creará.
El objeto arguments no es un Array. Si bien cuenta con la semántica
de un array - concretamente la propiedad length - no hereda de
Array.prototype y es de hecho un Objeto.
Debido a esto, no es posible usar los métodos estándar de los arrays como push,
pop o slice en arguments. Mientras que la iteración es un simple bucle for que
funciona muy bien, esto se convierte necesariamente en un Array real con el
fin de utilizar los métodos de un Array.
El siguiente código devuelve un nuevo Array que contiene todos los elementos del
objeto arguments.
Array.prototype.slice.call(arguments);
Esta conversión es lenta, no es recomendable usarlo en puntos criticos que afecten el rendimiento del código.
El siguiente método es recomendado para pasar argumentos desde una función a otra.
function foo() {
bar.apply(null, arguments);
}
function bar(a, b, c) {
// do stuff here
}
Otro truco es utilizar tanto call y apply juntos para crear contenedores rápidos y
consolidados.
function Foo() {}
Foo.prototype.method = function(a, b, c) {
console.log(this, a, b, c);
};
// Crea una versión sin consolidar de "method"
// Se toma los parámetros: this, arg1, arg2...argN
Foo.method = function() {
// Resultado: Foo.prototype.method.call(this, arg1, arg2... argN)
Function.call.apply(Foo.prototype.method, arguments);
};
El objeto arguments crea las funciones de getter y setter para sus
propiedades, así como parámetros formales de la función.
Como resultado, se ha cambiado el valor formal del parámetro también se cambio el
valor de la propiedad correspondiente del objeto arguments, y al revés.
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);
El objeto arguments es siempre creado con las dos únicas excepciones cuando es
el caso en que declarado como un nombre dentro de la función o uno de los
parámetros formales. No importa si se utiliza o no.
Ambos getters y setters son siempre creados; por lo tanto, con que casi no se
tiene un impacto en el rendimiento en todo, especialemente no en el código real donde no
es más que un simple acceso a las propiedades del objeto arguments.
Nota ES5: Estos getters y setters no son creados en modo estricto.
Sin embargo, hay casos en que se reducirá drásticamente el rendimiento en los motores
modernos de JavaScript. Este es el caso del uso de arguments.callee.
function foo() {
arguments.callee; // realiza algo con la función del objeto
arguments.callee.caller; // y llama a la función del objeto
}
function bigLoop() {
for(var i = 0; i < 100000; i++) {
foo(); // Debería ser normalmente entre líneas...
}
}
El código anterior, foo no puede estar sujeto a la expansión en línea ya que se
necesita saber acerca de sí mismo y la llamada. Esto no sólo denota los posibles beneficios
de rendimiento que surgen con la expansión en línea, ya que también interrumpe la encapsulación
ya que la función ahora puede ser dependiente de un contexto específico de llamada.
Es muy recomendable nunca hacer uso de arguments.callee o de cualquier
de sus propiedades.
Nota ES5: En modo estricto,
arguments.calleegenerará una excepción deTypeErrorya que su uso ha quedado obsoleto.