Dans un fichier JavaScript, j'ai vu:
function Somefunction(){
var that = this;
...
}
Quel est le but de la déclarer that
et de lui attribuer this
cela?
Dans un fichier JavaScript, j'ai vu:
function Somefunction(){
var that = this;
...
}
Quel est le but de la déclarer that
et de lui attribuer this
cela?
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é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
});
});
Parce que this
change fréquemment lorsque vous modifiez la portée en appelant une nouvelle fonction, vous ne pouvez pas accéder à la valeur d'origine en l'utilisant. that
Si vous le remplacez par, vous pouvez toujours accéder à la valeur d'origine de this
.
Personnellement, je n'aime pas l'utilisation de that
l'alias. Il est rarement évident de savoir à 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
.
var self = this;
. Le mot that
semble impliquer que la variable est n'importe quoi MAIS this
.
forEach
fonction prend un deuxième argument optionnel qui est la liaison de la fonction. colours.forEach(function(){/* 'this' is bound correctly --> */}, this);
Il faut donc ajouter une note qui var that = this
n'est pas réellement nécessaire avec forEach
.
Depuis Crockford
Par convention, nous faisons un privé que variable. Ceci est utilisé pour mettre l'objet à la disposition des méthodes privées. Il s'agit d'une solution de contournement pour une erreur dans la spécification de langage ECMAScript qui provoque ce paramètre n'est pas défini correctement pour les fonctions internes.
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 ...
Qui pense que ça s'appelle Dave
Usages Ceci pense que cela s'appelle undefined
that
variable n'est pas du tout utilisée dans son exemple. Cela donne l'impression que la simple création d'une variable holding this
fait quelque chose pour le reste du code.
Il s'agit d'un hack pour faire fonctionner les fonctions internes (fonctions définies à l'intérieur d'autres fonctions) comme elles le devraient. En javascript, lorsque vous définissez une fonction à l'intérieur d'une autre, elle est this
automatiquement définie sur la portée globale. Cela peut être déroutant car vous vous attendez this
à avoir 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 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, 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.
La création d'une variable à utiliser par convention dans les deux étendues est une solution à ce problème très général avec javascript (bien qu'il soit également utile dans les fonctions jquery). C'est pourquoi le nom à consonance très générale that
est utilisé. C'est une convention facilement reconnaissable pour surmonter une lacune dans la langue.
Comme El Ronnoco fait allusion à Douglas Crockford pense que c'est une bonne idée.
L'utilisation de that
n'est pas vraiment nécessaire si vous effectuez une solution de contournement en utilisant 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);
};
Parfois, this
peut faire référence à une autre portée et faire référence à autre chose, par exemple, supposons que vous vouliez 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
La solution ci - dessus assing this
pour that
ensuite nous pouvons et l' accès la propriété de nom dans la sayHi
méthode à partir that
, donc cela peut être appelé sans problèmes à l' intérieur de l'appel DOM.
Une autre solution consiste à lui affecter un that
objet vide et à lui ajouter des propriétés et des méthodes, puis à le renvoyer. Mais avec cette solution, vous avez perdu prototype
le constructeur.
var Person = function(name) {
var that = {};
that.name = name;
that.sayHi = function() {
alert(that.name);
};
return that;
};
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 this correspond à deux valeurs différentes selon l'élément DOM que vous ciblez, mais lorsque vous ajoutez "that" au code ci-dessus, vous modifiez la valeur de "this" 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 ".our-work-group> p> a" car la valeur de var that = this; donc même si nous sommes à "this" = '.our-work-single-page', nous pouvons toujours utiliser "that" pour manipuler l'élément DOM précédent.