W pliku JavaScript widziałem:
function Somefunction(){
var that = this;
...
}
Jaki jest cel zadeklarowania thati przypisania thistego do niego?
W pliku JavaScript widziałem:
function Somefunction(){
var that = this;
...
}
Jaki jest cel zadeklarowania thati przypisania thistego 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ż thisczę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 thatpozwala nadal uzyskać dostęp do pierwotnej wartościthis .
Osobiście nie lubię używania thatjako 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 thatwydaje się sugerować, że zmienna jest Cokolwiek, ALE this.
forEachFunkcji 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 = thistak 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
thatzmienna w ogóle nie jest użyta w jego przykładzie. Wygląda na to, że samo utworzenie zmiennej zmiennej thisma 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, thisautomatycznie ustawi się na zasięg globalny. Może to być mylące, ponieważ oczekuje thissię, ż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.startw przykładzie), a następnie tworzysz funkcję wewnątrz tej metody (jak activateStarter). W metodzie najwyższego poziomu thiswskazuje 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 thatnie 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 thismoż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 thisaby thatnastępnie możemy i mienia Nazwa dostępu wewnątrz sayHimetody zthat , tak to można nazwać bez problemów wewnątrz zaproszenia DOM.
Innym rozwiązaniem jest przypisanie pustego thatobiektu oraz dodanie do niego właściwości i metod, a następnie zwrócenie go. Ale dzięki temu rozwiązaniu straciłeś prototypekonstruktora.
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.