web-dev-qa-db-fra.com

Qu'est-ce que 'var that = this;' signifie 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'assigner à this?

344
Chris

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émontré à l’origine avec jQuery, 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
    });
});

Étant donné que this change fréquemment lorsque vous modifiez l'étendue en appelant une nouvelle fonction, vous ne pouvez pas accéder à la valeur d'origine en l'utilisant. L'aliasing sur that vous permet toujours d'accéder à la valeur d'origine de this.

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

475
lonesomeday

De Crockford

Par convention, nous faisons une variable privée que . Ceci est utilisé pour rendre l'objet disponible aux méthodes privées. Il s'agit d'une solution de contournement pour une erreur dans la spécification de langage ECMAScript qui entraîne la définition incorrecte de ce paramètre 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 ...

UsesQui pense qu'il s'appelle Dave

Cela s'appelle indéfini

103
El Ronnoco

C'est un hack pour faire en sorte que les fonctions internes (fonctions définies dans d'autres fonctions) fonctionnent mieux comme elles le devraient. En javascript, lorsque vous définissez une fonction dans une autre this est automatiquement définie 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;

    // 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();

};

Cela est particulièrement problématique lorsque vous créez une fonction en tant que méthode d'objet (comme car.start dans l'exemple), puis créez une fonction dans cette méthode (comme activateStarter). Dans la méthode de niveau supérieur, this pointe sur l'objet. Il s'agit d'une méthode de (dans ce cas, car), mais dans la fonction interne this pointe maintenant sur la portée globale. C'est pénible.

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 que cela soit utile dans les fonctions jquery également). C'est pourquoi le nom très général sonnant that est utilisé. C'est une convention facilement reconnaissable pour surmonter une lacune de la langue.

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

83
Waylon Flinn

L'utilisation de that n'est pas vraiment nécessaire si vous créez une solution de contournement 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
Adela

Parfois, this peut faire référence à une autre portée et à autre chose, par exemple, supposons que vous souhaitiez 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

<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 assage this à that alors nous pouvons et accéder à la propriété name à l'intérieur de la méthode sayHi à partir de that, afin qu'elle puisse être appelée sans problème à l'intérieur de l'appel DOM .

Une autre solution consiste à affecter un objet that vide et à lui ajouter des propriétés et des méthodes, puis à le renvoyer. Mais avec cette solution, vous avez perdu la prototype du constructeur.

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

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();
                    }
                });
            }

        });
    });`

Ainsi, vous pouvez voir que la valeur de cela correspond à deux valeurs différentes en fonction de l'élément DOM que vous ciblez, mais lorsque vous ajoutez "cela" au code ci-dessus, vous modifiez 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();
                    }
                });
            }

        });
    });`

..... $ (that) .css ("background-color", "# ffe700"); // Ici, la valeur de "that" est ". Notre-groupe de travail> p> a" car la valeur de var that = this; Ainsi, même si nous en sommes à "ceci" = ".notre-travail-page-unique", nous pouvons néanmoins utiliser "ça" pour manipuler un élément DOM précédent.

2
rshah