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

j'ai vu ce qui suit dans la source pour WebKit HTML 5 Notes De Stockage SQL Démo :

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 dans certains endroits (le corps de fonction) et ce dans d'autres endroits (les corps de fonctions définies dans la liste d'arguments des méthodes). Ce qui se passe? Maintenant que je l'ai remarqué une fois, vais-je commencer à le voir partout?

334
demandé sur DanMan 2009-06-07 18:59:29

10 réponses

voir cet "article 151930920" sur alistapart.com

self est utilisé pour maintenir 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 (particulièrement dans les fermetures).

410
répondu Jonathan Fingland 2016-10-25 15:27:51

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

pour éviter la confusion et les conflits potentiels, vous pouvez écrire var thiz = this ou var that = this à la place.

93
répondu Duan Yao 2016-05-03 11:03:21

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

Voir comment self est utilisé à l'intérieur des fonctions appelées par les événements? Ceux-ci auraient leur propre contexte, donc self est utilisé pour tenir le this qui est 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 la contexte de la fonction externe due à fermeture .

34
répondu Nosredna 2016-10-25 15:35:25

il faut aussi noter qu'il existe un autre modèle de procuration pour maintenir une référence à l'original this dans un rappel si vous n'aimez pas l'idiome 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 retourne une fonction qui appelle votre fonction avec apply ou call en utilisant le contexte donné. Voir la fonction proxy de jQuery pour une la mise en œuvre 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
répondu Max 2011-12-01 20:24:46

la variable est capturée par les fonctions en ligne définies dans la méthode. this dans la fonction se réfère à un autre objet. De cette façon, vous pouvez faire la fonction tenir une référence au this dans la portée extérieure.

9
répondu Mehrdad Afshari 2009-06-07 15:02:46

c'est une bizarrerie JavaScript. Lorsqu'une fonction est une propriété d'un objet, plus justement appelé une méthode, ce fait référence à l'objet. Dans l'exemple d'un gestionnaire d'événement, objet contenant, c'est l'élément qui a déclenché l'événement. Lorsqu'une fonction standard est invoquée, cette se réfère à l'objet global. Lorsque vous avez imbriqué des fonctions comme dans votre exemple, ce ne se rapporte pas au contexte de la fonction externe à tous. Les fonctions internes partagent la portée avec la fonction contenant, ainsi les développeurs utiliseront des variations de var that = this afin de préserver le ce dont ils ont besoin dans la fonction interne.

9
répondu kombat 2015-03-16 20:42:25

comme d'autres l'ont expliqué, var self = this; permet au code dans un fermeture de renvoyer à la portée principale.

cependant, il est maintenant 2018 et ES6 est largement pris en charge par tous les principaux navigateurs web. L'idiome var self = this; n'est plus aussi essentiel qu'il l'était.

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 de flèche

n'ont pas leur propre this et assument simplement la portée enveloppante.

6
répondu Elliot B. 2018-01-30 02:45:50

en fait self est une référence à window ( window.self ) donc quand vous dites var self = 'something' vous outrepassez une référence de window à elle - même-parce que self existe dans l'objet window.

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

de toute façon; var that = this; n'est pas conforme à la bonne pratique ... présumant que votre code sera révisé / modifié plus tard par d'autres développeurs, vous devriez utiliser la programmation la plus commune normes relatives à la communauté des développeurs

par conséquent, vous devriez utiliser quelque chose comme var oldThis / var oThis / etc - pour être clair dans votre champ d'application / / ..n'est pas que beaucoup, mais permettra d'économiser quelques secondes et quelques cycles du cerveau

5
répondu SorinN 2014-11-11 08:56:32

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

0
répondu Cyprien 2014-12-27 17:54:13
function Person(firstname, lastname) {
  this.firstname = firstname;

  this.lastname = lastname;
  this.getfullname = function () {
    return `${this.firstname}   ${this.lastname}`;
  };

  let that = this;
  this.sayHi = function() {
    console.log(`i am this , ${this.firstname}`);
    console.log(`i am that , ${that.firstname}`);
  };
}

let thisss = new Person('thatbetty', 'thatzhao');

let thatt = {firstname: 'thisbetty', lastname: 'thiszhao'};

thisss.sayHi.appel(que);

-1
répondu ht zhao 2018-08-02 05:16:06