W pliku JavaScript widziałem:
function Somefunction(){
var that = this;
...
}
Jaki jest cel zadeklarowania that
i przypisania this
tego do niego?
W pliku JavaScript widziałem:
function Somefunction(){
var that = this;
...
}
Jaki jest cel zadeklarowania that
i przypisania this
tego do niego?
Odpowiedzi:
Zacznę tę odpowiedź od ilustracji:
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
});
});
Moja odpowiedź pierwotnie wykazała to za pomocą jQuery, który tylko nieznacznie się różni:
$('#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
});
});
Ponieważ this
często zmienia się po zmianie zakresu przez wywołanie nowej funkcji, nie można uzyskać dostępu do pierwotnej wartości za jej pomocą. Aliasing do that
pozwala nadal uzyskać dostęp do pierwotnej wartościthis
.
Osobiście nie lubię używania that
jako aliasu. Rzadko jest oczywiste, do czego się odnosi, szczególnie jeśli funkcje są dłuższe niż kilka linii. I zawsze używać bardziej opisowego alias. W powyższych przykładach prawdopodobnie użyłbym clickedEl
.
var self = this;
. Słowo that
wydaje się sugerować, że zmienna jest Cokolwiek, ALE this
.
forEach
Funkcji zajmuje drugi opcjonalny argument, który jest wiązanie funkcji. colours.forEach(function(){/* 'this' is bound correctly --> */}, this);
Tak więc należy dodać notatkę, która var that = this
tak naprawdę nie jest potrzebna forEach
.
Umownie, wykonujemy prywatny że zmiennej. Służy to do udostępnienia obiektu metodom prywatnym. Jest to obejście błędu w specyfikacji języka ECMAScript, który powoduje to być nieprawidłowo ustawione dla funkcji wewnętrznych.
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);
To ostrzega ...
Używa, że to się nazywa Dave
Używa: Sądzi się, że nazywa się to niezdefiniowane
that
zmienna w ogóle nie jest użyta w jego przykładzie. Wygląda na to, że samo utworzenie zmiennej zmiennej this
ma wpływ na resztę kodu.
To jest hack, aby funkcje wewnętrzne (funkcje zdefiniowane wewnątrz innych funkcji) działały bardziej tak, jak powinny. W javascript, gdy zdefiniujesz jedną funkcję w innej, this
automatycznie ustawi się na zasięg globalny. Może to być mylące, ponieważ oczekuje this
się, że będzie miała taką samą wartość jak w funkcji zewnętrznej.
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();
};
Jest to szczególnie problem, gdy tworzysz funkcję jako metodę obiektu (jak car.start
w przykładzie), a następnie tworzysz funkcję wewnątrz tej metody (jak activateStarter
). W metodzie najwyższego poziomu this
wskazuje na obiekt, jest to metoda (w tym przypadku car
), ale w funkcji wewnętrznejthis
wskazuje teraz na zasięg globalny. To jest ból.
Utworzenie zmiennej do użycia zgodnie z konwencją w obu zakresach jest rozwiązaniem tego bardzo ogólnego problemu z javascript (chociaż jest także użyteczny w funkcjach jquery). Właśnie dlatego bardzo ogólna brzmiąca nazwathat
używana jest . Jest to łatwo rozpoznawalna konwencja w przezwyciężaniu niedociągnięć w języku.
Jak El Ronnoco w Douglas Crockford uważa, że to dobry pomysł.
Użycie that
nie jest tak naprawdę konieczne, jeśli obejdziesz to za pomocą call()
lub 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);
};
Czasami this
może odnosić się do innego zakresu i odnosić się do czegoś innego, na przykład załóżmy, że chcesz wywołać metodę konstruktora wewnątrz zdarzenia DOM, w tym przypadkuthis
odniesie się do elementu DOM, a nie do utworzonego obiektu.
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
Rozwiązanie powyżej woli assing this
aby that
następnie możemy i mienia Nazwa dostępu wewnątrz sayHi
metody zthat
, tak to można nazwać bez problemów wewnątrz zaproszenia DOM.
Innym rozwiązaniem jest przypisanie pustego that
obiektu oraz dodanie do niego właściwości i metod, a następnie zwrócenie go. Ale dzięki temu rozwiązaniu straciłeś prototype
konstruktora.
var Person = function(name) {
var that = {};
that.name = name;
that.sayHi = function() {
alert(that.name);
};
return that;
};
Oto przykład `
$(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();
}
});
}
});
});`
Możesz więc zobaczyć, że ta wartość to dwie różne wartości w zależności od elementu DOM, na który celujesz, ale dodając „to” do powyższego kodu, zmieniasz wartość „tego”, na który celujesz.
`$(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 („kolor tła”, „# ffe700”); // Tutaj wartością „tego” jest „.our-work-group> p> a”, ponieważ wartość var that = this; więc mimo tego, że jesteśmy w „this” = '.our-work-single-page ”, nadal możemy użyć„ tego ”do manipulowania poprzednim elementem DOM.