Funktionsaufruf mit gebundenem this-Wert
Es gibt zwei Hauptfälle, in denen es sinnvoll ist, den this-Wert selbst zu definieren. Bei einer Callback-Funktion, und wenn man eine Methode einer Variable zuweisen möchte. Bevor wir uns mit der this-Bindung beschäftigen, ist es wichtig zu verstehen, warum solch eine Bindung überhaupt nötig ist.
Normalerweise wird in JavaScript der this-Wert beim Funktionsaufruf gebunden. Derjenige, der die Funktion aufruft, definiert auch den this-Wert. Wird zum Beispiel eine Funktion als Methode aufgerufen, wird this das Objekt sein. Bei einem normalen Funktionsaufruf ist this das window-Objekt im normalen Modus oder undefined im strict-Modus.
function fn() {
console.log(this);
}
var obj = {
fn: fn
};
// Funktion wird als Methode aufgerufen
obj.fn(); // this ist das Objekt obj
// Normaler Funktionsaufruf
fn(); // this ist das window-Objekt
Um eine this-Bindung zu realisieren, können wir die Function.prototype.bind-Funktion benutzen. Diese Funktion bekommt als ersten Parameter den this-Wert und gibt eine Funktion mit gebundenem this-Wert zurück. Alle weiteren Parameter sind optional. Was man damit anfangen kann, steht in unserem Blogartikel über partielle Funktionsanwendung.
Beispiel für eine this-Bindung mit Methode
var obj = {
name: 'Max',
getName: function() {
return this.name;
}
};
// Aufruf als Methode
// this-Wert ist an das Objekt gebunden
obj.getName; // 'Max'
// Zuweisung an Variable
var getName = obj.getName;
// Normaler Funktionsaufruf
// this-Wert ist an das window-Objekt gebunden
getName(); // undefined
In Zeile 9 wurde der this-Wert an das Objekt obj gebunden wie erwartet. Aber in Zeile 15 wurde der this-Wert an das window-Objekt gebunden, und darum ist das Resultat des Aufrufs undefined. Eine mögliche Lösung ist es, bei der Zuweisung den this-Wert an das Objekt obj zu binden.
var obj = {
name: 'Max',
getName: function() {
return this.name;
}
};
// this-Wert von getName() an das obj binden
var getName = obj.getName.bind(obj);
getName(); // 'Max'
Jetzt ist der this-Wert der getName()-Funktion an obj gebunden, und der getName()-Aufruf funktioniert wie erwartet.
Beispiel für eine this-Bindung mit Callback
Ein ähnliches Problem wie oben sehen wir auch, wenn wir this in einem Callback benutzen wollen. Die klassische Lösung ist es, den this-Wert einer anderen Variablen zuzuweisen wie unten dargestellt.
var obj = {
name: 'Max',
fn: function() {
var that = this;
function callback() {
console.log('Name', that.name); // 'Max'
console.log(this); // this ist das window-Objekt
}
setTimeout(callback, 0);
}
};
obj.fn();
Diese Lösung funktioniert ohne Probleme und wird auch sehr häufig benutzt, aber wir können das Problem auch mit Hilfe von bind() lösen. Hier derselbe Code, aber diesmal mit bind().
var obj = {
name: 'Max',
fn: function() {
var callback = function () {
console.log('Name', this.name); // 'Max'
console.log(this); // das Objekt obj
}.bind(this);
}
};
obj.fn();
Beide Lösungen sind meiner Meinung nach nicht besonders schön. In Zukunft werden wir noch eine weitere Möglichkeit haben, und zwar Arrow-Funktionen.