191 votes

var self = this ?

L'utilisation de méthodes d'instance en tant que rappels pour les gestionnaires d'événements modifie la portée de la méthode this de "Mon instance a "Quoi qu'il en soit, je viens d'appeler le service de rappel" . Mon code ressemble donc à ceci

function MyObject() {
  this.doSomething = function() {
    ...
  }

  var self = this
  $('#foobar').bind('click', function(){
    self.doSomethng()
    // this.doSomething() would not work here
  })
}

Cela fonctionne, mais est-ce la meilleure façon de procéder ? Cela me semble étrange.

17 votes

Vous devez éviter self car il existe un window.self et vous pourriez finir par l'utiliser accidentellement si vous oubliez de déclarer votre propre objet self var (par exemple en déplaçant du code). Cela peut être gênant à repérer/déboguer. Il est préférable d'utiliser quelque chose comme _this .

5 votes

3 votes

A partir de la Tutoriel JavaScript : "La valeur de this est dynamique en JavaScript. Elle est déterminée lorsque la fonction est appelé et non lorsqu'elle est déclarée".

218voto

Eugene Lazutkin Points 22414

Cette question n'est pas spécifique à jQuery, mais à JavaScript en général. Le problème principal est de savoir comment "canaliser" une variable dans des fonctions intégrées. Voici l'exemple :

var abc = 1; // we want to use this variable in embedded functions

function xyz(){
  console.log(abc); // it is available here!
  function qwe(){
    console.log(abc); // it is available here too!
  }
  ...
};

Cette technique repose sur l'utilisation d'une fermeture. Mais elle ne fonctionne pas avec this parce que this est une pseudo-variable qui peut changer dynamiquement d'une portée à l'autre :

// we want to use "this" variable in embedded functions

function xyz(){
  // "this" is different here!
  console.log(this); // not what we wanted!
  function qwe(){
    // "this" is different here too!
    console.log(this); // not what we wanted!
  }
  ...
};

Que pouvons-nous faire ? L'assigner à une variable et l'utiliser par le biais de l'alias :

var abc = this; // we want to use this variable in embedded functions

function xyz(){
  // "this" is different here! --- but we don't care!
  console.log(abc); // now it is the right object!
  function qwe(){
    // "this" is different here too! --- but we don't care!
    console.log(abc); // it is the right object here too!
  }
  ...
};

this n'est pas unique à cet égard : arguments est l'autre pseudo-variable qui doit être traitée de la même manière - par aliasing.

7 votes

Vous devriez vraiment lier "this" à l'appel de la fonction et ne pas le faire circuler ou traverser les champs d'application des variables avec lui.

10 votes

@michael Pourquoi ?

0 votes

@michael il se peut que tu travailles à l'intérieur de pipe, map, subscribees... dans une fonction et que tu n'appelles pas les fonctions, dans ce cas "this" change, donc la portée de la variable est la solution.

41voto

Jaime Febres Points 729

Un bon article qui explique ces petites questions en javascript est celui-ci :

http://www.alistapart.com/articles/getoutbindingsituations

J'espère que cela vous aidera.

18voto

BenAlabaster Points 20189

Oui, cela semble être une norme commune. Certains codeurs utilisent self, d'autres me. Il s'agit d'une référence à l'objet "réel" par opposition à l'événement.

Il m'a fallu un peu de temps pour comprendre ce phénomène, qui semble étrange au premier abord.

Je le fais généralement au début de mon objet (excusez mon code de démonstration - il est plus conceptuel qu'autre chose et n'est pas une leçon sur une excellente technique de codage) :

function MyObject(){
  var me = this;

  //Events
  Click = onClick; //Allows user to override onClick event with their own

  //Event Handlers
  onClick = function(args){
    me.MyProperty = args; //Reference me, referencing this refers to onClick
    ...
    //Do other stuff
  }
}

3voto

neonski Points 772

Je n'ai pas utilisé jQuery, mais dans une bibliothèque comme Prototype, vous pouvez lier des fonctions à un champ d'application spécifique. En gardant cela à l'esprit, votre code ressemblerait à ceci :

 $('#foobar').ready('click', this.doSomething.bind(this));

La méthode bind renvoie une nouvelle fonction qui appelle la méthode d'origine avec la portée que vous avez spécifiée.

0 votes

Analogue à : $('#foobar').ready('click', this.doSomething.call(this)); n'est-ce pas ?

0 votes

En bind ne fonctionne pas dans les anciens navigateurs, il faut donc utiliser la méthode $.proxy à la place.

3voto

Javier Points 33134

Oui, c'est une véritable bouée de sauvetage (ou mieux, un "sanitysaver"). bien sûr, je me suis fait rétrograder pour avoir affirmé qu'il s'agissait d'une des bévues de la mauvaise conception du langage en JS.

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