Skip to content

Latest commit

 

History

History
119 lines (83 loc) · 4.13 KB

File metadata and controls

119 lines (83 loc) · 4.13 KB

El objeto arguments

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 arguments ya se ha definido dentro del ámbito de la función ya sea através de la sentencia var o como un parámetro formal, el objeto arguments no 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.

Conversión 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.

Pasar Argumentos

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);
};

Los parámetros formales y argumentos de índices

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);

Mitos y verdades sobre el rendimiento

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.callee generará una excepción de TypeError ya que su uso ha quedado obsoleto.