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 de l'affecter à this ?

316
demandé sur DavidRR 2011-02-03 16:21:51

6 réponses

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 l'a d'abord démontré avec jQuery, ce qui n'est que 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 souvent quand vous changez la portée en appelant une nouvelle fonction, vous ne pouvez pas accéder à la valeur originale en l'utilisant. L'alias 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 fait référence, surtout si les fonctions sont plus longues que quelques lignes. J' toujours utiliser un plus descriptif alias. Dans les exemples ci-dessus, j'utiliserais probablement clickedEl .

444
répondu lonesomeday 2014-07-10 11:40:14

À Partir De Crockford

par convention, nous faisons un privé que variable. Ceci est utilisé pour faire de l' objet disponible pour le privé méthode. C'est une solution de contournement pour un erreur dans le langage ECMAScript Spécification qui fait que ce est incorrectement définies pour les fonctions internes.

js Fiddle

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

    function returnMe() {
        return this;        //scope is lost because of the inner function
    }

    return {
        returnMe : returnMe
    }
}

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

    function returnMe() {
        return that;            //scope is baked in with 'that' to the "class"
    }

    return {
        returnMe : returnMe
    }
}

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

cette Alerte...

Usthat thinks it's called Dave

UsesThis pense qu'il est appelé indéfini

96
répondu El Ronnoco 2016-03-15 10:14:40

il s'agit d'un hack pour faire fonctionner les fonctions internes (définies dans d'autres fonctions) comme elles devraient le faire. En javascript, lorsque vous définissez une fonction à l'intérieur d'une autre this est automatiquement défini à la portée globale. Cela peut prêter à confusion 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;

    // you can access car.starter inside this method with 'this'
    this.starter.active = false;

    var activateStarter = function(){
        // 'this' now points to the global scope
        // 'this.starter' is undefined, so we use 'that' instead.
        that.starter.active = true;

        // you could also use car.starter, but using 'that' gives
        // us more consistency and flexibility
    };

    activateStarter();

};

C'est spécifiquement un problème lorsque vous créez une fonction comme une méthode d'un objet (comme car.start dans le exemple) puis créer une fonction à l'intérieur de cette méthode (comme activateStarter ). Dans la méthode du niveau supérieur this pointe vers l'objet c'est une méthode de (dans ce cas, car ) mais dans la fonction interne this pointe maintenant vers la portée globale. C'est une douleur.

créer une variable à utiliser par convention dans les deux sens est une solution pour ce problème très général avec javascript (bien qu'il soit utile dans les fonctions jquery, aussi). C'est pourquoi le son très général le nom that est utilisé. Il est facilement reconnaissable convention pour surmonter une lacune dans la langue.

Comme El Ronnoco allusion à de Douglas Crockford pense que c'est une bonne idée.

80
répondu Waylon Flinn 2013-10-30 15:08:50

L'utilisation de that n'est pas vraiment nécessaire si vous apporter une solution avec l'utilisation de call() ou apply() :

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

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

    var activateStarter = function(){
        // 'this' now points to our main object
        this.starter.active = true;
    };

    activateStarter.apply(this);
};
8
répondu Adela 2015-11-15 05:40:40

parfois this peut se référer à une autre portée et se référer à autre chose, par exemple supposons que vous voulez appeler une méthode de constructeur à l'intérieur d'un événement DOM, dans ce cas this se référera à l'élément DOM et non à l'objet créé.

HTML

<button id="button">Alert Name</button>

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

Démo

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

une autre solution consiste à attribuer un objet vide that et à y ajouter des propriétés et des méthodes, puis à le retourner. Mais avec cette solution, vous avez perdu le prototype du constructeur.

var Person = function(name) {
  var that = {};
  that.name = name;
  that.sayHi = function() {
    alert(that.name);
  };
  return that;
};
2
répondu Ahmad Ajmi 2014-11-01 11:51:37

Voici un exemple

$(document).ready(function() {
        var lastItem = null;
        $(".our-work-group > p > a").click(function(e) {
            e.preventDefault();

            var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
            if (item == lastItem) {
                lastItem = null;
                $('.our-work-single-page').show();
            } else {
                lastItem = item;
                $('.our-work-single-page').each(function() {
                    var imgAlt = $(this).find('img').attr('alt'); //Here value of "this" is '.our-work-single-page'. 
                    if (imgAlt != item) {
                        $(this).hide();
                    } else {
                        $(this).show();
                    }
                });
            }

        });
    });`

donc vous pouvez voir que la valeur de ceci est deux valeurs différentes selon L'élément DOM que vous ciblez mais quand vous ajoutez" que "au code ci-dessus vous changez la valeur de" ceci " que vous ciblez.

`$(document).ready(function() {
        var lastItem = null;
        $(".our-work-group > p > a").click(function(e) {
            e.preventDefault();
            var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
            if (item == lastItem) {
                lastItem = null;
                var that = this;
                $('.our-work-single-page').show();
            } else {
                lastItem = item;
                $('.our-work-single-page').each(function() {
                   ***$(that).css("background-color", "#ffe700");*** //Here value of "that" is ".our-work-group > p > a"....
                    var imgAlt = $(this).find('img').attr('alt'); 
                    if (imgAlt != item) {
                        $(this).hide();
                    } else {
                        $(this).show();
                    }
                });
            }

        });
    });`

..... $(qui).css ("background-color", "#ffe700"); //ici valeur de" cela "est".notre-groupe de travail > p> a " parce que la valeur de var qui = cela, alors même si nous sommes à "ce"= '.notre-work-single-page', nous pouvons toujours utiliser "that" pour manipuler L'élément DOM précédent.

2
répondu user5313842 2015-11-30 21:38:24