web-dev-qa-db-fra.com

Qu'est-ce qui sous-tend cet idiome JavaScript: var self = this?

J'ai vu ce qui suit dans le code source de démonstration de WebKit HTML 5 SQL Storage Notes :

function Note() {
  var self = this;

  var note = document.createElement('div');
  note.className = 'note';
  note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
  note.addEventListener('click', function() { return self.onNoteClick() }, false);
  this.note = note;
  // ...
}

L'auteur utilise self à certains endroits (le corps de la fonction) et this à d’autres endroits (les corps de fonctions définis dans la liste d’arguments des méthodes). Que se passe-t-il? Maintenant que je l'ai remarqué une fois, vais-je commencer à le voir partout?

347
Thomas L Holaday

Voir ceci article sur alistapart.com

self est utilisé pour conserver une référence à l'original this même si le contexte change. C'est une technique souvent utilisée dans les gestionnaires d'événements (surtout dans les fermetures).

420

Je pense que le nom de variable 'self' ne devrait plus être utilisé de cette façon, car les navigateurs modernes fournissent un variable globale self pointant vers l'objet global d'une fenêtre normale ou d'un WebWorker.

Pour éviter toute confusion et tout conflit potentiel, vous pouvez écrire var thiz = this ou var that = this à la place.

96
Duan Yao

Oui, vous le verrez partout. C'est souvent that = this;.

Voyez comment self est utilisé dans les fonctions appelées par les événements? Ceux-ci auraient leur propre contexte, donc self est utilisé pour contenir le this entré dans Note().

La raison pour laquelle self est toujours disponible pour les fonctions, même si elles ne peuvent être exécutées qu'après l'exécution de la fonction Note(), est que les fonctions internes obtiennent le contexte de la fonction externe en raison de fermeture .

34
Nosredna

Il convient également de noter qu’il existe un modèle de proxy alternatif permettant de conserver une référence à la variable this originale dans un rappel si vous n’aimez pas le langage var self = this.

Comme une fonction peut être appelée avec un contexte donné en utilisant function.apply ou function.call, vous pouvez écrire un wrapper qui renvoie une fonction qui appelle votre fonction avec apply ou call à l'aide de le contexte donné. Voir la fonction proxy de jQuery pour une implémentation de ce modèle. Voici un exemple d'utilisation:

var wrappedFunc = $.proxy(this.myFunc, this);

wrappedFunc peut alors être appelé et aura votre version de this comme contexte.

28
Max

C'est une bizarrerie JavaScript. Lorsqu'une fonction est une propriété d'un objet, plus communément appelée méthode, this se réfère à l'objet. Dans l'exemple d'un gestionnaire d'événement, l'objet conteneur est l'élément qui a déclenché l'événement. Lorsqu'une fonction standard est appelée, this fera référence à l'objet global. Lorsque vous avez des fonctions imbriquées, comme dans votre exemple, this ne concerne pas du tout le contexte de la fonction externe. Les fonctions internes partagent la même étendue que la fonction qui les contient. Les développeurs utilisent donc des variantes de var that = this afin de conserver le this dont ils ont besoin dans la fonction interne.

9
kombat

La variable est capturée par les fonctions en ligne définies dans la méthode. this dans la fonction fera référence à un autre objet. De cette façon, vous pouvez faire en sorte que la fonction maintienne une référence à la this dans la portée externe.

9
Mehrdad Afshari

Comme d'autres l'ont expliqué, var self = this; permet au code d'une fermeture de renvoyer à la portée parente.

Cependant, nous sommes maintenant en 2018 et ES6 est largement pris en charge par tous les principaux navigateurs Web. Le langage var self = this; n'est plus aussi essentiel qu'auparavant.

Il est maintenant possible d'éviter var self = this; grâce à l'utilisation de fonctions de flèche .

Dans les cas où nous aurions utilisé var self = this:

function test() {
    var self = this;
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", function() {
        console.log(self.hello); // logs "world"
    });
};

Nous pouvons maintenant utiliser une fonction de flèche sans var self = this:

function test() {
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", () => {
        console.log(this.hello); // logs "world"
    });
};

Les fonctions fléchées n'ont pas leur propre this et supposent simplement la portée englobante.

8
Elliot B.

En réalité, self est une référence à window (window.self) donc lorsque vous dites var self = 'something', vous remplacez une référence de fenêtre à elle-même - car self existe dans un objet window.

C'est pourquoi la plupart des développeurs préfèrent var that = this à var self = this;

En tous cas; var that = this; n'est pas conforme à la bonne pratique ... en supposant que votre code soit révisé/modifié ultérieurement par d'autres développeurs, vous devez utiliser les normes de programmation les plus courantes pour les développeurs.

Par conséquent, vous devriez utiliser quelque chose comme var oldThis/var oThis/etc - pour être clair dans votre champ d'application, ce n'est pas beaucoup, mais vous économiserez quelques secondes et quelques cycles cérébraux.

5
SorinN

Comme mentionné à plusieurs reprises ci-dessus, "self" est simplement utilisé pour conserver une référence à "this" avant d'entrer dans la fonction. Une fois dans la fonction 'ceci' se réfère à autre chose.

0
Cyprien