Das Schlüsselwort this
bezieht sich auf den Wert des Objekts, das zum Zeitpunkt des Aufrufs an die Funktion gebunden ist. Der Wert ist also unterschiedlich, je nachdem, ob eine Funktion als Methode, als eigenständige Funktion oder als Konstruktor aufgerufen wird.
Wenn eine Funktion aufgerufen wird, wird im Hintergrund eine Instanz des Schlüsselworts this
als Verweis auf das Objekt erstellt, das diese Funktion enthält. Dadurch wird innerhalb des Gültigkeitsbereichs Zugriff auf die darin definierten Eigenschaften und Methoden gewährt.
Die Arbeit mit this
ähnelt in gewisser Weise der Arbeit mit einer Variablen, die mit const
deklariert wurde. Wie eine Konstante kann this
nicht entfernt und sein Wert nicht neu zugewiesen werden. Die Methoden und Eigenschaften des Objekts, das das this
-Keyword enthält, können jedoch geändert werden.
Globale Bindung
Außerhalb einer Funktion oder des Kontexts eines Objekts bezieht sich this
auf das globalThis
-Attribut, das in den meisten JavaScript-Umgebungen eine Referenz auf das globale Objekt ist. Im Kontext eines Scripts, das in einem Webbrowser ausgeführt wird, ist das window
-Objekt das globale Objekt:
this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}
In Node.js ist globalThis
das global
-Objekt:
$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> this
<ref *1> Object [global] {
...
}
Außerhalb des strengen Modus bezieht sich this
auch auf das globale Objekt in einer eigenständigen Funktion, da das übergeordnete Window
das Objekt ist, dem diese Funktionen „zugewiesen“ sind.
function myFunction() {
console.log( this );
}
myFunction();
> Window {...}
(function() {
console.log( this );
}());
> Window {...}
Im strengen Modus hat this
in einer eigenständigen Funktion den Wert undefined
:
(function() {
"use strict";
console.log( this );
}());
> undefined
Vor der Einführung des strengen Modus wurde ein null
- oder undefined
-Wert für this
durch einen Verweis auf das globale Objekt ersetzt. Aufgrund dieses alten Verhaltens wird die globale Bindung manchmal auch als „Standardbindung“ bezeichnet.
Impliziter Verweis
Wenn eine Funktion als Methode eines Objekts aufgerufen wird, bezieht sich eine Instanz von this
in dieser Methode auf das Objekt, das die Methode enthält. Dadurch wird Zugriff auf die zugehörigen Methoden und Eigenschaften gewährt:
let myObject = {
myValue: "This is my string.",
myMethod() {
console.log( this.myValue );
}
};
myObject.myMethod();
> "This is my string."
Es sieht so aus, als würde der Wert von this
davon abhängen, wie eine Funktion und das umschließende Objekt definiert sind. Stattdessen ist der Kontext für den Wert von this
der aktuelle Ausführungskontext. In diesem Fall ruft das myObject
-Objekt die myMethod
-Methode auf. Daher ist myObject
der Wert für this
. Im Kontext der vorherigen Beispiele mag das wie eine Kleinigkeit erscheinen, aber bei erweiterten Verwendungen von this
ist es eine wichtige Unterscheidung, die Sie beachten sollten.
Verwenden Sie this
im Allgemeinen so, dass der umgebende Code keine bestimmte Struktur hat. Eine Ausnahme von dieser Regel sind Arrow-Funktionen in ES5.
this
in Pfeilfunktionen
In Pfeilfunktionen wird this
in einer lexikalisch umschließenden Umgebung auf eine Bindung aufgelöst. Das bedeutet, dass sich this
in einer Pfeilfunktion auf den Wert von this
im übergeordneten Kontext dieser Funktion bezieht:
let myObject = {
myMethod() { console.log( this ); },
myArrowFunction: () => console.log( this ),
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myMethod();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
myObject.myArrowFunction();
> Window {...}
Im vorherigen Beispiel wird in myObject.myMethod()
myObject
als das Objekt protokolliert, zu dem diese Methode gehört. myObject.myArrowFunction()
gibt jedoch globalThis
(oder undefined
) zurück, da sich die Instanz von this
in der Pfeilfunktion stattdessen auf den übergeordneten Gültigkeitsbereich bezieht.
Im folgenden Beispiel erstellt myEnclosingMethod
eine Pfeilfunktion auf dem Objekt, das sie enthält, wenn sie ausgeführt wird. Die Instanz von this
innerhalb der Pfeilfunktion bezieht sich jetzt auf den Wert von this
in der umschließenden Umgebung, also der Methode, die diese Pfeilfunktion enthält. Da sich der Wert von this
in myEnclosingMethod
auf myObject
bezieht, bezieht sich this
in der Pfeilfunktion nach der Definition der Pfeilfunktion ebenfalls auf myObject
:
let myObject = {
myMethod() { console.log( this ); },
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myEnclosingMethod();
myObject.myArrowFunction();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
Explizite Bindung
Die implizite Bindung deckt die meisten Anwendungsfälle für die Arbeit mit this
ab. Manchmal ist es jedoch erforderlich, dass der Wert von this
einen bestimmten Ausführungskontext anstelle des angenommenen Kontexts darstellt. Ein anschauliches, wenn auch etwas veraltetes Beispiel ist die Arbeit mit this
in der Callback-Funktion einer setTimeout
, da dieser Callback einen eindeutigen Ausführungskontext hat:
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
myObject.myMethod();
> "This is my string."
setTimeout( myObject.myMethod, 100 );
> undefined
Obwohl dieser spezifische Mangel von setTimeout
inzwischen durch andere Funktionen behoben wurde, wurden ähnliche Probleme mit dem „Verlieren“ von this
in der Vergangenheit durch einen expliziten Verweis auf den Wert von this
im Rahmen des beabsichtigten Kontexts behoben. In älteren Codebases werden Variablen gelegentlich mithilfe von IDs wie that
, self
oder _this
einer Instanz von this
zugewiesen. Dies sind gängige Konventionen für Variablen, die einen übergebenen this
-Wert enthalten.
Wenn Sie eine Funktion mit den Methoden call()
, bind()
oder apply()
aufrufen, verweist this
ausdrücklich auf das aufgerufene Objekt:
let myFunction = function() {
console.log( this.myValue );
}
let myObject = {
"myValue" : "This is my string."
};
myFunction.call( myObject );
> "This is my string."
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
setTimeout( myObject.myMethod.bind( myObject ), 100 );
> "This is my string."
Durch die explizite Bindung wird der this
-Wert überschrieben, der durch die implizite Bindung bereitgestellt wird.
let myObject = {
"myValue" : "This string sits alongside myMethod.",
myMethod() {
console.log( this.myValue );
}
};
let myOtherObject = {
"myValue" : "This is a string in another object entirely.",
};
myObject.myMethod.call( myOtherObject );
> "This is a string in another object entirely."
Wenn eine Funktion so aufgerufen wird, dass der Wert von this
auf undefined
oder null
festgelegt wird, wird dieser Wert außerhalb des strengen Modus durch globalThis
ersetzt:
let myFunction = function() {
console.log( this );
}
myFunction.call( null );
> Window {...}
Wenn eine Funktion auf eine Weise aufgerufen wird, dass this
einen primitiven Wert erhält, wird dieser Wert außerhalb des strengen Modus durch das Wrapper-Objekt des primitiven Werts ersetzt:
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> Number { 10 }
Im strengen Modus wird ein übergebener this
-Wert in keiner Weise in ein Objekt umgewandelt, auch wenn es sich um einen primitiven Wert, einen null
-Wert oder einen undefined
-Wert handelt:
"use strict";
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> 10
myFunction.call( null );
> null
new
-Bindung
Wenn eine Klasse als Konstruktor mit dem Schlüsselwort new
verwendet wird, bezieht sich this
auf die neu erstellte Instanz:
class MyClass {
myString;
constructor() {
this.myString = "My string.";
}
logThis() {
console.log( this );
}
}
const thisClass = new MyClass();
thisClass.logThis();
> Object { myString: "My string." }
Ebenso bezieht sich der Wert von this
in einer Konstruktorfunktion, die mit new
aufgerufen wird, auf das erstellte Objekt:
function MyFunction() {
this.myString = "My string.";
this.logThis = function() {
console.log( this );
}
}
const myObject = new MyFunction();
myObject.logThis();
> Object { myString: "My string.", logThis: logThis() }
Event-Handler-Bindung
Im Kontext von Event-Handlern verweist der Wert von this
auf das Objekt, das ihn aufruft. In der Callback-Funktion eines Ereignis-Handlers verweist this
also auf das Element, das mit dem Handler verknüpft ist:
let button = document.querySelector( "button" );
button.addEventListener( "click", function( event ) { console.log( this ); } );
Wenn ein Nutzer mit dem button
im vorherigen Snippet interagiert, ist das Ergebnis das Elementobjekt, das die <button>
selbst enthält:
> Button {}
Wenn eine Pfeilfunktion als Callback für einen Ereignis-Listener verwendet wird, wird der Wert von this
wieder vom nächstgelegenen umschließenden Ausführungskontext bereitgestellt. Auf oberster Ebene bedeutet das, dass this
in einer Callback-Funktion des Ereignis-Handlers globalThis
ist:
let button = document.querySelector( "button" );
button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined
Wie bei jedem anderen Objekt wird auch bei this
die Callback-Funktion eines Ereignis-Listeners mithilfe der Methoden call()
, bind()
oder apply()
referenziert:
let button = document.querySelector( "button" );
let myObject = {
"myValue" : true
};
function handleClick() {
console.log( this );
}
button.addEventListener( "click", handleClick.bind( myObject ) );
> Object { myValue: true }
Wissen testen
Auf welches globale Objekt bezieht sich this
bei einem Script, das in einem Webbrowser ausgeführt wird, wenn es außerhalb einer Funktion oder des Kontexts eines Objekts verwendet wird?
window
-Objektbrowser
-Objektundefined
-Objekt