Sigue un extracto de Cierre: La guía definitiva de Michael Bolin . Puede parecer un poco largo, pero está saturado con mucha información. Del "Apéndice B. Conceptos de JavaScript frecuentemente malinterpretados":
A qué se this
refiere cuando se llama una función
Cuando se llama a una función de la forma foo.bar.baz()
, el objeto foo.bar
se denomina receptor. Cuando se llama a la función, es el receptor el que se utiliza como valor para this
:
var obj = {};
obj.value = 10;
/** @param {...number} additionalValues */
obj.addValues = function(additionalValues) {
for (var i = 0; i < arguments.length; i++) {
this.value += arguments[i];
}
return this.value;
};
// Evaluates to 30 because obj is used as the value for 'this' when
// obj.addValues() is called, so obj.value becomes 10 + 20.
obj.addValues(20);
Si no hay un receptor explícito cuando se llama a una función, el objeto global se convierte en el receptor. Como se explica en "goog.global" en la página 47, la ventana es el objeto global cuando JavaScript se ejecuta en un navegador web. Esto lleva a un comportamiento sorprendente:
var f = obj.addValues;
// Evaluates to NaN because window is used as the value for 'this' when
// f() is called. Because and window.value is undefined, adding a number to
// it results in NaN.
f(20);
// This also has the unintentional side effect of adding a value to window:
alert(window.value); // Alerts NaN
A pesar de que obj.addValues
y f
se refieren a la misma función, se comportan de manera diferente cuando se llama así porque el valor del receptor es diferente en cada llamada. Por esta razón, cuando se llama a una función que hace referencia this
, es importante asegurarse de que this
tendrá el valor correcto cuando se llame. Para ser claros, si this
no se hiciera referencia en el cuerpo de la función, el comportamiento de f(20)
y obj.addValues(20)
sería el mismo.
Como las funciones son objetos de primera clase en JavaScript, pueden tener sus propios métodos. Todas las funciones tienen los métodos call()
y apply()
permiten redefinir el receptor (es decir, el objeto al que se this
refiere) cuando se llama a la función. Las firmas del método son las siguientes:
/**
* @param {*=} receiver to substitute for 'this'
* @param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* @param {*=} receiver to substitute for 'this'
* @param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;
Tenga en cuenta que la única diferencia entre call()
y apply()
es que call()
recibe los parámetros de la función como argumentos individuales, mientras que los apply()
recibe como una sola matriz:
// When f is called with obj as its receiver, it behaves the same as calling
// obj.addValues(). Both of the following increase obj.value by 60:
f.call(obj, 10, 20, 30);
f.apply(obj, [10, 20, 30]);
Las siguientes llamadas son equivalentes, como f
y obj.addValues
se refieren a la misma función:
obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);
Sin embargo, dado que call()
ni apply()
utiliza el valor de su propio receptor para sustituir el argumento del receptor cuando no está especificado, lo siguiente no funcionará:
// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);
El valor de this
nunca puede ser null
o undefined
cuando se llama a una función. Cuando null
o undefined
se suministra como el receptor a call()
o apply()
, el objeto global se usa como el valor para el receptor. Por lo tanto, el código anterior tiene el mismo efecto secundario no deseado de agregar una propiedad nombrada value
al objeto global.
Puede ser útil pensar que una función no tiene conocimiento de la variable a la que está asignada. Esto ayuda a reforzar la idea de que el valor de esto estará vinculado cuando se llama a la función en lugar de cuando se define.
Fin del extracto.
a
en solicitar matriz de argumentos yc
en solicitar columnas de argumentos.