153 votes

Différence entre this et self en JavaScript

Tout le monde est conscient de this en javascript, mais il existe également des instances de self rencontrés dans la nature, tels que aquí

Alors, quelle est la différence entre this y self en JavaScript ?

167voto

Paul S. Points 20115

Sauf si elle est définie ailleurs, la valeur de self es window parce que JavaScript vous permet d'accéder à n'importe quelle propriété x de window comme simplement x au lieu de window.x . Par conséquent, self est vraiment window.self qui est différent de this .

window.self === window; // true

Si vous utilisez une fonction qui est exécutée dans la portée globale et qui n'est pas en mode strict, this La valeur par défaut est window et donc

function foo() {
    console.log(
        window.self === window, // is self window?
        window.self === this,   // is self this?
        this === window         // is this window?
    );
}
foo(); // true true true

Si vous utilisez une fonction dans un contexte différent, this fera référence à ce contexte, mais self sera toujours window .

// invoke foo with context {}
foo.call({}); // true false false

Vous pouvez trouver window.self défini dans le Projet de travail du W3C 2006 pour le Objet fenêtre aquí .

51voto

AndyHasIt Points 740

Un léger ajout à ce sujet car les gens peuvent rencontrer ce terme dans le contexte des travailleurs du secteur des services, auquel cas il a une signification légèrement différente.

Vous pouvez voir cela dans un module de travailleur de service :

self.addEventListener('install', function(e) {
  console.log('[ServiceWorker] Install');
});

Aquí self fait référence au WorkerGlobalScope, et il s'agit de la méthode standard pour définir les récepteurs d'événements.

Desde Documents de Mozilla :

En utilisant self, vous pouvez faire référence à la portée globale d'une manière qui fonctionnera non seulement dans un contexte de fenêtre (self sera résolu par window.self) mais aussi dans un contexte de travailleur (self sera alors résolu par WorkerGlobalScope.self).

28voto

Shashank Vivek Points 3858

Bien que je sois en retard, j'ai trouvé un exemple qui peut aussi aider à comprendre. this plus loin :

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);
    (function() {
        console.log("inner func:  this.foo = " + this.foo);
        console.log("inner func:  self.foo = " + self.foo);
    }());
  }
};
myObject.func();

O/P

outer func:  this.foo = bar
outer func:  self.foo = bar
inner func:  this.foo = undefined
inner func:  self.foo = bar

Avant l'ECMA 5, this dans la fonction interne se réfère à l'objet fenêtre global, alors qu'à partir de ECMA 5, this dans la fonction interne serait indéfinie.

2voto

Uber Kluger Points 185

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 l'ECMA-262 (alias ECMAScript ou, de façon moins précise, Javascript) est un langage de script général qui a été mis en œuvre dans les navigateurs Internet. De la norme Edition 5.1 :

Les étapes suivantes sont effectuées lorsque le contrôle entre dans le contexte d'exécution pour le code de fonction contenu dans l'objet de fonction F, un appelant fourni thisArg, et un appelant fourni argumentsList :

  1. Si le code de la fonction est un code strict, définissez le ThisBinding sur thisArg.
  2. Sinon, si thisArg est nul ou indéfini, définir le ThisBinding à l'objet global.
  3. Sinon, si le Type(thisArg) n'est pas Object, définissez le ThisBinding sur ToObject(thisArg).
  4. Else définir le ThisBinding à thisArg
  5. ... (pas sur "ça")

Le terme "objet global" désigne l'objet qui se trouve au sommet de la chaîne de portée. Pour les navigateurs, il s'agirait de l'objet "window", mais il s'agit d'un choix d'implémentation (l'hôte Windows script possède un objet global invisible mais pas de mode strict, de sorte que les références non qualifiées accèdent à ses propriétés et qu'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). Ainsi, un "this" non défini serait toujours résolu comme l'objet global (fenêtre) dans "ECMA 5" avec le mode strict non activé.

Donc la réponse à la question est :

"this" fait toujours référence à l'objet qui invoque la fonction. Si la fonction n'a pas été invoquée par un objet (c'est-à-dire qu'il ne s'agit pas d'un appel de méthode), alors "this" (tel que transmis à la fonction) est "undefined". Toutefois, si vous n'utilisez PAS le mode strict, un "this" indéfini est défini comme l'objet global (règle 2 ci-dessus).

"self" n'a pas de signification syntaxique particulière, il s'agit simplement d'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 à "self" sont identiques à "window" À MOINS QUE "self" 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 la suivante :

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 avant d'être invoquée par votreObjet. Ainsi, 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é retourné, était (et dans la fermeture résultante est toujours) myObject. Ainsi, dans la fonction interne, "this" fait référence à l'objet qui appelle la fonction interne, tandis que "self" fait référence à 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é, "this" est défini par la norme du langage, "self" est défini par celui qui le définit (implémenteur du runtime ou programmeur final).

0voto

SridharKritha Points 346

Trouvez ci-dessous quelques combinaisons de sorties de console 'window', 'self' et 'this' dans la portée globale (environnement du navigateur) pour voir à quoi il fait référence.

console.log( window ); // Window {…}
console.log( self );   // Window {…}
console.log( this );   // Window {…}

console.log( window.window ); // Window {…}
console.log( window.self );   // Window {…}
console.log( window.this );   // undefined  

console.log( self.self );     // Window {…}
console.log( self.window );   // Window {…}
console.log( self.this );     // undefined

console.log( this.this );     // undefined
console.log( this.window );   // Window {…}
console.log( this.self );     // Window {…}

console.log( window.window.window );    // Window {…}
console.log( self.self.self );          // Window {…}
console.log( window.self.window.self ); // Window {…}
console.log( self.window.self.window ); // Window {…}
console.log( this.this );               // undefined

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X