Nilai kata kunci `this` dari suatu fungsi dikembalikan dari pengambil

15

Saya menemukan nilai tak terduga dari kata kunci ini dalam contoh berikut:

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


x.func1(x)

Nilai kata kunci ini adalah objek x seolah-olah dieksekusi dari objek itu, saya berharap hanya fungsi get yang memiliki kata kunci ini sama dengan objek panggilan x

contoh ini menunjukkan kepada kita perbedaannya

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

x.func2()(x);

Dalam kedua contoh func1 yang merupakan fungsi pengambil, dan func2 yang merupakan metode objek, dieksekusi dari objek x , dan fungsi yang dikembalikan kemudian dieksekusi. Jadi mengapa nilai ini dalam contoh pertama tidak sama dengan objek global, bukan objek x .

Kirollos Nasr
sumber
3
Sungguh, pertanyaan yang sangat menarik. Saya belum pernah memikirkan kerutan ini sebelumnya.
TJ Crowder
1
" Seolah-olah itu dijalankan dari objek yang " - tetapi yang dijalankan pada objek itu, di sana: x.func1().
Bergi

Jawaban:

13

Itu pertanyaan yang sangat menarik.

Itu karena fungsi dipanggil segera pada hasil dari akses properti. Jadi ini secara fundamental setara:

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

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

Dalam kedua kasus:

  1. Nilai properti dibaca, menghasilkan referensi fungsi.
  2. Fungsi itu dijalankan sebagai bagian dari ekspresi akses properti yang sama.

Fakta bahwa itu func1adalah properti accessor dan func2properti data tidak masalah. Begitulah nilai yang dihasilkan dari membaca properti digunakan yang penting.

TJ Crowder
sumber
1
Saya berpikir bahwa seluruh ekspresi akan dievaluasi ke objek fungsi dan kemudian dieksekusi. Terima kasih
Kirollos Nasr
1
@KirollosNasr Ya, benar, tetapi dalam ekspresi x.func1itu menyimpan referensi xsebagai konteks untuk panggilan berikutnya, berbeda dengan x.func2()(dari pertanyaan Anda) yang mengevaluasi fungsi juga tetapi bukan ekspresi akses anggota.
Bergi
1
@Bergi - saya pikir maksud Anda x.func2()(x);?
TJ Crowder
1
@TJCrowder Ya, saya merujuk pada ekspresi di dalam x.func1(x)danx.func2()(x)
Bergi
1
@Bergi ya itu memiliki bagian yang sulit. Tapi sekarang lebih jelas Terima kasih kepada TJ Crowder dan Anda
Kirollos Nasr