386 votes

Que signifie 'var that = this;' en JavaScript?

Dans un fichier JavaScript, j'ai vu :

function Somefunction(){
   var that = this; 
   ... 
}

Quel est le but de déclarer that et d'assigner this à celui-ci ?

3 votes

Possible duplicate de var self = this?

9 votes

Le hack "this" et "that" n'est pas nécessaire pour les fonctions fléchées. Avec les fonctions fléchées, "this" fonctionne comme prévu. Voir ici pour plus de détails ES6 En Profondeur: Fonctions fléchées

1 votes

Ici le concept de ceci est expliqué scotch.io/@alZami/understanding-this-in-javascript

520voto

lonesomeday Points 95456

Je vais commencer cette réponse par une illustration :

var colours = ['red', 'green', 'blue'];
document.getElementById('element').addEventListener('click', function() {
    // this is a reference to the element clicked on

    var that = this;

    colours.forEach(function() {
        // this is undefined
        // that is a reference to the element clicked on
    });
});

Ma réponse initiale démontrait cela avec jQuery, qui est seulement très légèrement différent :

$('#element').click(function(){
    // this is a reference to the element clicked on

    var that = this;

    $('.elements').each(function(){
        // this is a reference to the current element in the loop
        // that is still a reference to the element clicked on
    });
});

Parce que this change fréquemment lorsque vous changez la portée en appelant une nouvelle fonction, vous ne pouvez pas accéder à la valeur originale en l'utilisant. L'alias en that vous permet toujours d'accéder à la valeur originale de this.

Personnellement, je n'aime pas l'utilisation de that comme alias. Il est rarement évident à quoi il se réfère, surtout si les fonctions sont plus longues que quelques lignes. J'utilise toujours un alias plus descriptif. Dans mes exemples ci-dessus, j'utiliserais probablement clickedEl.

161 votes

Je vais généralement avec var self = this;. Le mot that semble impliquer que la variable est tout SAUF this.

13 votes

@David Oui, j'ai pensé que c'est quelque peu trompeur. Mais si, comme le dit Crockford, c'est une convention, est-il judicieux d'emprunter cette voie. Je suis totalement d'accord avec toi cependant, cela a beaucoup plus de sens.

0 votes

@David : Voici mes pensées, var that = this et je me demande ce que c'est? Si l'implémentation utilisait self, je n'aurais probablement même pas eu à me poser la question.

116voto

El Ronnoco Points 5941

De Crockford

Par convention, nous créons une variable privée that. Ceci est utilisé pour rendre l'objet disponible pour les méthodes privées. C'est une solution de contournement pour une erreur dans la spécification du langage ECMAScript, qui provoque une mauvaise définition de this pour les fonctions internes.

JS Fiddle

function usesThis(name) {
    this.myName = name;

    function returnMe() {
        return this;        //la portée est perdue en raison de la fonction interne
    }

    return {
        returnMe : returnMe
    }
}

function usesThat(name) {
    var that = this;
    this.myName = name;

    function returnMe() {
        return that;            //la portée est incluse avec 'that' dans la "classe"
    }

    return {
        returnMe : returnMe
    }
}

var usesthat = new usesThat('Dave');
var usesthis = new usesThis('John');
alert("UsesThat pense s'appeler " + usesthat.returnMe().myName + '\r\n' +
      "UsesThis pense s'appeler " + usesthis.returnMe().myName);

Ceci affiche une alerte...

UsesThat pense s'appeler Dave

UsesThis pense s'appeler undefined

2 votes

Merci, cela résume bien pour moi.

3 votes

J'ai lu cela, je n'ai pas compris parce qu'il n'y avait pas de détails, j'ai cherché sur Google, j'ai trouvé cette page. Où je suis à nouveau dirigé vers la même phrase. D'où le vote négatif.

3 votes

C'est un point juste, je dirais que quelqu'un qui n'est pas familier avec JavaScript aurait du mal à saisir le concept juste avec ma réponse. J'ai répondu très brièvement (et j'ai mis un lien vers la page sur laquelle vous avez fait une recherche..) Je dirais que la réponse de lonesomeday est la plus claire, bien que j'aurais quand même préféré qu'elle soit en JS pur plutôt qu'en exemple jQuery.

91voto

Waylon Flinn Points 8140

Ceci est une astuce pour rendre les fonctions internes (fonctions définies à l'intérieur d'autres fonctions) plus efficaces. En javascript, lorsque vous définissez une fonction à l'intérieur d'une autre, this est automatiquement défini sur la portée globale. Cela peut être déroutant car vous vous attendez à ce que this ait la même valeur que dans la fonction externe.

var car = {};
car.starter = {};

car.start = function(){
    var that = this;

    // vous pouvez accéder à car.starter à l'intérieur de cette méthode avec 'this'
    this.starter.active = false;

    var activateStarter = function(){
        // 'this' pointe maintenant vers la portée globale
        // 'this.starter' est indéfini, donc nous utilisons 'that' à la place.
        that.starter.active = true;

        // vous pourriez aussi utiliser car.starter, mais utiliser 'that' donne
        // plus de consistance et de flexibilité
    };

    activateStarter();

};

C'est spécifiquement un problème lorsque vous créez une fonction en tant que méthode d'un objet (comme car.start dans l'exemple), puis créez une fonction à l'intérieur de cette méthode (comme activateStarter). Dans la méthode de niveau supérieur this pointe vers l'objet dont il s'agit d'une méthode (dans ce cas, car) mais dans la fonction interne this pointe maintenant vers la portée globale. C'est embêtant.

Créer une variable à utiliser par convention dans les deux portées est une solution à ce problème très général avec javascript (bien qu'elle soit également utile dans les fonctions jquery). C'est pourquoi le nom très général that est utilisé. C'est une convention facilement reconnaissable pour surmonter une lacune dans le langage.

Comme El Ronnoco le suggère, Douglas Crockford pense que c'est une bonne idée.

8 votes

Je suppose que cette réponse est plus utile que celle acceptée. Car elle clarifie la raison pour laquelle Crockford a inventé "that" tandis que la réponse sur jQuery ne le fait pas.

5 votes

Il s'agit en fait d'un meilleur exemple que la réponse acceptée. Il explique ce que c'est comme "une erreur dans la spécification du langage ECMAScript qui entraîne que cela est incorrectement défini pour les fonctions internes", comme l'a dit Douglas.

1 votes

Vous voudrez peut-être le rendre grammaticalement correct cependant. Je sais que c'est plus comme une faute de frappe, mais cela pourrait confondre les débutants en JavaScript car cette question est plutôt destinée aux débutants. Je veux dire que cela devrait être : var voiture = {}; voiture.démarrer = {}; voiture.démarrer = function() {...}

11voto

Adela Points 101

L'utilisation de that n'est pas vraiment nécessaire si vous contournez en utilisant call() ou apply():

var car = {};
car.starter = {};

car.start = function(){
    this.starter.active = false;

    var activateStarter = function(){
        // 'this' points maintenant vers notre objet principal
        this.starter.active = true;
    };

    activateStarter.apply(this);
};

3voto

λhmad λjmi Points 821

Parfois this peut faire référence à une autre portée et référencer autre chose, par exemple supposez que vous voulez appeler une méthode constructeur à l'intérieur d'un événement DOM, dans ce cas this fera référence à l'élément DOM et non à l'objet créé.

HTML

Alert Name

JS

var Person = function(name) {
  this.name = name;
  var that = this;
  this.sayHi = function() {
    alert(that.name);
  };
};

var ahmad = new Person('Ahmad');
var element = document.getElementById('button');
element.addEventListener('click', ahmad.sayHi); // => Ahmad

Demo

La solution ci-dessus assignera this à that, puis nous pouvons accéder à la propriété name à l'intérieur de la méthode sayHi à partir de that, donc cela peut être appelé sans problèmes à l'intérieur de l'appel DOM.

Une autre solution est d'assigner un objet vide that et d'y ajouter des propriétés et des méthodes, puis de le renvoyer. Mais avec cette solution, vous perdez le prototype du constructeur.

var Person = function(name) {
  var that = {};
  that.name = name;
  that.sayHi = function() {
    alert(that.name);
  };
  return that;
};

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