Der Wert des Schlüsselworts `this` einer Funktion, die von einem Getter zurückgegeben wurde

15

Ich habe im folgenden Beispiel einen unerwarteten Wert dieses Schlüsselworts gefunden:

let x = {
    z : 10 ,
    get func1() {
        return function(v) {
            console.log(this === v);
        }
    }
}


x.func1(x)

Der Wert dieses Schlüsselworts ist das Objekt x, als ob es von diesem Objekt ausgeführt wird. Ich erwarte nur die Funktion get , die es gibt dieses Schlüsselwort hat, dem aufrufenden Objekt x entspricht

Dieses Beispiel zeigt uns den Unterschied

let x = {
    func2() {
        return function(v) {
            console.log(this === v);
        }
    }
}

x.func2()(x);

In beiden Beispielen werden func1, die die Getter-Funktion ist, und func2, die eine Methode des Objekts ist, vom Objekt x ausgeführt , und die zurückgegebene Funktion wird dann ausgeführt. Warum entspricht dieser Wert im ersten Beispiel nicht dem globalen Objekt anstelle des Objekts x ?

Kirollos Nasr
quelle
3
Wirklich sehr, sehr interessante Frage. Ich hätte noch nie an diese Falte gedacht.
TJ Crowder
1
" als ob es von diesem Objekt ausgeführt wird " - aber es wird für dieses Objekt ausgeführt, genau dort : x.func1().
Bergi

Antworten:

13

Das ist ein sehr interessante Frage.

Dies liegt daran, dass die Funktion sofort nach dem Ergebnis eines Eigenschaftszugriffs aufgerufen wird. Diese sind also grundsätzlich gleichwertig:

let x = {
    get func1() {
        return function(v) {
            console.log(this === v);
        };
    },
    func2(v) {
        console.log(this === v);
    }
};

x.func1(x);
x.func2(x);

In beiden Fällen:

  1. Der Wert der Eigenschaft wird gelesen, was zu einer Funktionsreferenz führt.
  2. Diese Funktion wird als Teil desselben Eigenschaftszugriffsausdrucks ausgeführt.

Die Tatsache, dass func1es sich um eine Accessor-Eigenschaft und func2eine Dateneigenschaft handelt, spielt keine Rolle. Es kommt darauf an, wie der Wert verwendet wird, der sich aus dem Lesen der Eigenschaft ergibt.

TJ Crowder
quelle
1
Ich dachte, dass der gesamte Ausdruck für das Funktionsobjekt ausgewertet und dann ausgeführt wird. Danke, verstanden
Kirollos Nasr
1
@KirollosNasr Ja, das ist es, aber im Ausdruck x.func1wird der Verweis xals Kontext für den nachfolgenden Aufruf beibehalten , im Gegensatz zu x.func2()(aus Ihrer Frage), die ebenfalls eine Funktion auswertet, aber kein Mitgliedszugriffsausdruck ist.
Bergi
1
@Bergi - ich denke du meintest x.func2()(x);?
TJ Crowder
1
@TJCrowder Ja, ich beziehe mich auf die Ausdrücke im Inneren x.func1(x)undx.func2()(x)
Bergi
1
@Bergi Ja, es hat einen schwierigen Teil. Aber jetzt ist es klarer Dank an TJ Crowder und Sie
Kirollos Nasr