La référence à l'ECMA 5 doit être clarifiée.
Je suppose que cela signifie ECMA-262 Edition 5. Il convient de noter que ECMA-262 (aka ECMAScript ou, moins précisément, Javascript) est un langage de script général qui a été implémenté dans les navigateurs Internet. À partir de la norme Edition 5.1:
Les étapes suivantes sont effectuées lorsque le contrôle entre dans le contexte d'exécution du code de fonction contenu dans l'objet de fonction F, un appelant a fourni thisArg et un appelant a fourni argumentsList:
- Si le code de fonction est un code strict, définissez ThisBinding sur thisArg.
- Sinon, si thisArg est nul ou non défini, définissez ThisBinding sur l'objet global.
- Sinon, si Type (thisArg) n'est pas Object, définissez ThisBinding sur ToObject (thisArg).
- Sinon, définissez ThisBinding sur thisArg
- ... (pas à propos de "ceci")
Le terme «objet global» fait référence à tout objet qui se trouve en haut de la chaîne de portée. Pour les navigateurs, ce serait l'objet "window" mais c'est un choix d'implémentation (Windows Script Host a un objet global invisible mais pas de mode strict donc des références non qualifiées accèdent à ses propriétés et il n'y a pas de "self" global). De plus, le "mode strict" doit être explicitement activé sinon il n'est pas actif (section 14.1 de la norme). En tant que tel, un "this" non défini résoudrait toujours l'objet global (fenêtre) dans "ECMA 5" avec le mode strict non actif.
La réponse à la question est donc:
"this" fait toujours référence à l'objet qui appelle la fonction. Si la fonction n'a pas été invoquée par un objet (c'est-à-dire pas un appel de méthode), alors "this" (tel que passé à la fonction) est "indéfini". Cependant, si vous n'utilisez PAS le mode strict, un "this" non défini est défini sur l'objet global (règle 2 ci-dessus).
"self" n'a pas de signification syntaxique particulière, c'est juste un identifiant. Les navigateurs ont tendance à définir window.self (juste une propriété de l'objet global window) = window. Il en résulte que les références non qualifiées à «soi» sont identiques à «fenêtre» À MOINS QUE «soi» n'ait été redéfini dans une portée englobante (comme par «var self = this;» ci-dessus. Bonne chance pour redéfinir «this».)
L'explication complète de l'exemple ci-dessus est donc:
outer func: this.foo = bar
// "this" refers to the invoking object "myObject"
outer func: self.foo = bar
// "self" resolves to the variable in the local scope which has been set to "this" so it is also "myObject"
inner func: this.foo = undefined
// "this" refers to the invoking object (none) and so is replaced by the global object (strict mode must be off). "window" has no foo property so its "value" is undefined.
inner func: self.foo = bar
// self resolves to the variable in the enclosing scope which is still "myObject"
Une variante intéressante de l'exemple crée une fermeture en renvoyant une référence à la fonction interne.
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
return function() {
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
};
}
};
var yourObject = {
foo: "blat",
func: myObject.func() // function call not function object
};
console.log("----");
yourObject.func();
Produire
outer func: this.foo = bar
outer func: self.foo = bar
----
inner func: this.foo = blat
inner func: self.foo = bar
Notez que la fonction interne n'est pas appelée tant qu'elle n'est pas appelée par yourObject. Donc this.foo est maintenant yourObject.foo mais self se résout toujours à la variable dans la portée englobante qui, au moment où l'objet de la fonction interne a été renvoyé, était (et dans la fermeture résultante est toujours) myObject. Ainsi, dans la fonction interne, «ceci» fait référence à l'objet appelant la fonction interne tandis que «soi» se réfère à l'objet qui a appelé la fonction externe pour créer la référence à la fonction interne.
Pour résumer le résumé du résumé, «ceci» est défini par le standard du langage, «self» est défini par celui qui le définit (exécuteur ou programmeur final).