Programmeren in JavaScript/Objecten/thisthat
Ditjes en datjes
bewerkenWat is het probleem?
bewerkenthis binnen een functie refereert naar het object van waaruit de functie werd aangeroepen (en dus niet het object waar de functie een methode van is).
Bekijk het volgende "object"
JavaScript-code: Wat is Dit?
function constructor(naam)
{
this.name = naam;
this.methode = function()
{
writeln("methode: " + this + this.name);
}
writeln("Object klaar: " + this + this.name);
}
var obj = new constructor("myObject")
obj.methode();
document.getElementById("writespace").onclick = obj.methode;
// Uitvoer:
// Object klaar: [object Object]myObject
// methode: [object Object]myObject
// methode: [object HTMLDivElement] undefined (na click op "writespace")
De laatste regel is een beetje tegen de verwachting in, als je het vergelijkt met andere programmeertalen.
Oplossing:
bewerkenIntroduceer in de constructor een lokale variabele "that" en maak die gelijk aan this. "that" bevat dus een verwijzing naar het object dat met de constructor is aangemaakt. In de methode die ik als eventhandler wil gebruiken vervang ik this door that.
JavaScript-code: Dat is Dit!
function constructor(naam)
{
var that = this;
this.name = naam;
this.methode = function()
{
writeln("methode: " + that + that.name);
}
writeln("Object klaar: " + this + this.name);
}
var obj = new constructor("myObject")
obj.methode();
document.getElementById("writespace").onclick = obj.methode;
// Uitvoer:
// Object klaar: [object Object]myObject
// methode: [object Object]myObject
// methode: [object Object]myObject (na click op "writespace")
Alternatieve oplossingen
bewerkencall en apply
bewerkencall en apply zijn members van het Function prototype, hetgeen betekent dat je someFunction.call() of someFunction.apply() kunt aanroepen, net als someFunction.toString(). call en apply zijn identiek, behalve in de manier waarop parameters worden meegegeven.
Hoewel met behulp van call of apply een functie kan worden aangeroepen alsof dit vanuit een bepaald object gebeurt, is het niet mogelijk iets van de vorm this.methode.call(this) toe te wijzen als event handler.
bind
bewerkenVanaf IE9 heeft de function ook een method "bind" waarmee kan worden gezorgd dat een methode altijd wordt aangeroepen alsof hij vanuit het object zelf werd aangeroepen.
JavaScript-code: Bind
function constructor(naam)
{
this.name = naam;
this.methode = function()
{
writeln("methode: " + this + this.name);
}.bind(this);
document.getElementById("writespace").onclick = this.methode;
writeln("Object klaar: " + this + this.name);
}
Afgezien van het feit dat de methode niet in wat oudere browsers beschikbaar is, (bepaalde libraries kunnen daar helpen) kost deze methode meer cpu-tijd dan de "that" methode. Dus als de "that" methode toepasbaar is verdient die de voorkeur.