Das Keyword

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?

Das window-Objekt
Das browser-Objekt
Das undefined-Objekt