Suit un extrait de Closure: The Definitive Guide de Michael Bolin . Cela peut sembler un peu long, mais il est saturé de beaucoup de perspicacité. Extrait de "Annexe B. Concepts JavaScript fréquemment mal compris":
À quoi fait this
référence lorsqu'une fonction est appelée
Lors de l'appel d'une fonction du formulaire foo.bar.baz()
, l'objet foo.bar
est appelé récepteur. Lorsque la fonction est appelée, c'est le récepteur qui est utilisé comme valeur pour 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);
S'il n'y a pas de récepteur explicite lorsqu'une fonction est appelée, alors l'objet global devient le récepteur. Comme expliqué dans "goog.global" à la page 47, la fenêtre est l'objet global lorsque JavaScript est exécuté dans un navigateur Web. Cela conduit à un comportement surprenant:
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
Même si obj.addValues
et f
reportez - vous à la même fonction, ils se comportent différemment lorsqu'il est appelé parce que la valeur du récepteur est différent dans chaque appel. Pour cette raison, lors de l'appel d'une fonction qui fait référence this
, il est important de s'assurer qu'elle this
aura la bonne valeur lors de son appel. Pour être clair, s'ils this
n'étaient pas référencés dans le corps de la fonction, le comportement de f(20)
et obj.addValues(20)
serait le même.
Comme les fonctions sont des objets de première classe en JavaScript, elles peuvent avoir leurs propres méthodes. Toutes les fonctions ont des méthodes call()
et apply()
qui permettent de redéfinir le récepteur (c'est-à-dire l'objet auquel il se this
réfère) lors de l'appel de la fonction. Les signatures de méthode sont les suivantes:
/**
* @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;
Notez que la seule différence entre call()
et apply()
est que call()
reçoit les paramètres de la fonction sous forme d'arguments individuels, alors qu'il les apply()
reçoit sous la forme d'un tableau unique:
// 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]);
Les appels suivants sont équivalents f
et obj.addValues
font référence à la même fonction:
obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);
Cependant, puisque call()
ni apply()
n'utilise la valeur de son propre récepteur pour remplacer l'argument récepteur lorsqu'il n'est pas spécifié, les éléments suivants ne fonctionneront pas:
// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);
La valeur de this
ne peut jamais être null
ou undefined
lorsqu'une fonction est appelée. Lorsque null
ou undefined
est fourni en tant que récepteur à call()
ou apply()
, l'objet global est utilisé à la place comme valeur pour le récepteur. Par conséquent, le code précédent a le même effet secondaire indésirable que l'ajout d'une propriété nommée value
à l'objet global.
Il peut être utile de considérer une fonction comme n'ayant aucune connaissance de la variable à laquelle elle est affectée. Cela permet de renforcer l'idée que la valeur de ceci sera liée lorsque la fonction est appelée plutôt que lorsqu'elle est définie.
Fin de l'extrait.
a
à appliquer un tableau d'arguments etc
à appeler des colonnes d'arguments.