Wartość słowa kluczowego `this` funkcji zwróconej z gettera

15

W poniższym przykładzie znalazłem nieoczekiwaną wartość tego słowa kluczowego:

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


x.func1(x)

Wartością tego słowa kluczowego jest obiekt x, tak jakby został wykonany z tego obiektu, oczekuję, że tylko funkcja get, która ma to słowo kluczowe, jest równa obiektowi wywołującemu x

ten przykład pokazuje nam różnicę

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

x.func2()(x);

W obu przykładach func1, która jest funkcją gettera, i func2, która jest metodą obiektu, są wykonywane z obiektu x , a następnie zwracana funkcja jest wykonywana. Dlaczego więc ta wartość w pierwszym przykładzie nie jest równa obiektowi globalnemu zamiast obiektowi x .

Kirollos Nasr
źródło
3
Naprawdę bardzo interesujące pytanie. Nigdy wcześniej nie myślałam o tej zmarszczce.
TJ Crowder
1
Jakby to wykonany z tego obiektu ” - ale to jest wykonywane na tym obiekcie, tam: x.func1().
Bergi

Odpowiedzi:

13

To bardzo interesujące pytanie.

Jest tak, ponieważ funkcja jest wywoływana natychmiast po uzyskaniu dostępu do właściwości. Są to zasadniczo równoważne:

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

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

W obu przypadkach:

  1. Wartość właściwości jest odczytywana, co powoduje odwołanie do funkcji.
  2. Ta funkcja jest wykonywana jako część tego samego wyrażenia dostępu do właściwości.

Fakt, że func1jest to właściwość akcesorium i func2właściwość danych, nie ma znaczenia. Liczy się sposób, w jaki używana jest wartość wynikająca z odczytu właściwości.

TJ Crowder
źródło
1
Myślałem, że całe wyrażenie zostanie ocenione do obiektu funkcji, a następnie wykonane. Dzięki,
rozumiem
1
@KirollosNasr Tak, tak, ale w wyrażeniu x.func1zachowuje odniesienie xjako kontekst dla następnego wywołania, w przeciwieństwie do x.func2()(z twojego pytania), które ocenia również funkcję, ale nie jest wyrażeniem dostępu do członka.
Bergi
1
@Bergi - Myślę, że miałeś na myśli x.func2()(x);?
TJ Crowder
1
@TJCrowder Tak, odnoszę się do wyrażeń wewnątrz x.func1(x)ix.func2()(x)
Bergi
1
@Bergi tak, ma trudną część. Ale teraz jest bardziej jasne Dzięki TJ Crowder i tobie
Kirollos Nasr