Hvordan får man adgang til den korrekte `this` i en callback?
Jeg har en konstruktionsfunktion, som registrerer en hændelseshåndtering:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
Men jeg kan ikke få adgang til data
-egenskaben for det oprettede objekt inden for callback'en. Det ser ud til, at this
ikke henviser til det objekt, der blev oprettet, men til et andet objekt.
Jeg har også forsøgt at bruge en objektmetode i stedet for en anonym funktion:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
men det udviser de samme problemer.
Hvordan kan jeg få adgang til det korrekte objekt?
1300
3
Hvad du bør vide om
this
this
(også kendt som "konteksten") er et særligt nøgleord i hver funktion, og dets værdi afhænger kun af hvordan funktionen blev kaldt, ikke hvordan/hvornår/hvor den blev defineret. Det er ikke påvirket af leksikale scopes som andre variabler (undtagen for pilefunktioner, se nedenfor). Her er nogle eksempler:Hvis du vil vide mere om
this
, kan du tage et kig på [MDN-dokumentationen][this].Sådan henviser du til den korrekte
this
Brug ikke
this
Du ønsker faktisk ikke at få adgang til
this
i særdeleshed, men det objekt det refererer til. Derfor er en nem løsning blot at oprette en ny variabel, der også refererer til dette objekt. Variablen kan have et hvilket som helst navn, men almindelige navne erself
ogthat
.Da
self
er en normal variabel, overholder den reglerne for leksikalsk rækkevidde og er tilgængelig inde i callbacken. Dette har også den fordel, at du kan få adgang til værdienthis
i selve callbacken.Eksplicit indstilling af
this
i callback - del 1Det kan se ud som om, at du ikke har nogen kontrol over værdien af
this
, fordi dens værdi sættes automatisk, men det er faktisk ikke tilfældet.Hver funktion har metoden [
.bind
[docs]][bind], som returnerer en ny funktion medthis
bundet til en værdi. Funktionen har nøjagtig samme opførsel som den, du kaldte.bind
på, blot erthis
sat af dig. Uanset hvordan eller hvornår funktionen kaldes, vilthis
altid henvise til den overgivne værdi.Det hele ligger i den "magiske" syntaks for at kalde en metode:
Når du henter egenskaben fra objektet og kalder den på én gang, vil objektet være kontekst for metoden. Hvis du kalder den samme metode, men i separate trin, er konteksten i stedet det globale scope (vinduet):
Når du får referencen til en metode, er den ikke længere knyttet til objektet, det er bare en reference til en almindelig funktion. Det samme sker, når du får referencen til brug som callback:
Det er der, hvor du binder konteksten til funktionen:
Hvis du bruger jQuery, skal du bruge metoden
$.proxy
i stedet, dabind
ikke understøttes i alle browsere:Problemet med "kontekst"
Udtrykket "context" bruges nogle gange til at henvise til det objekt, der refereres til af this. Brugen er uhensigtsmæssig, fordi den hverken semantisk eller teknisk passer til ECMAScript's this.
"Kontekst" betyder de omstændigheder, der omgiver noget, som giver mening, eller nogle forudgående og efterfølgende oplysninger, som giver ekstra mening. Udtrykket "kontekst" bruges i ECMAScript til at henvise til udførelseskontekst, som er alle parametre, anvendelsesområde og this inden for anvendelsesområdet for en eller anden eksekverende kode.
Dette er vist i ECMA-262 afsnit 10.4.2:
hvilket klart angiver, at Dette er en del af en udførelseskontekst.
En eksekveringskontekst giver de omgivende oplysninger, der giver mening til den kode, der udføres. Den indeholder meget mere information end blot thisBinding.
Så værdien af this er ikke "kontekst", det er blot en del af en eksekveringskontekst. Det er i bund og grund en lokal variabel, der kan sættes af opkaldet til et hvilket som helst objekt og i strict mode til en hvilken som helst værdi overhovedet.