* Kemungkinan besar, saya melewatkan sesuatu, tetapi saya yakin komentar akan mengatakan ini kepada sayaSaya menulis artikel ini untuk kebutuhan pribadi saya. Direncanakan bahwa itu akan berisi jawaban atas semua pertanyaan yang diajukan siswa kepada saya mengenai topik ini. Jika ini berguna untuk orang lain - hebat.
Konten
- Pendahuluan
- Kesalahpahaman tentang ini
- Cara menentukan nilai ini
Pendahuluan
Kata
this
adalah salah satu fitur yang paling membingungkan dari bahasa JavaScript. Berasal dari Jawa, itu dimaksudkan untuk membantu dalam implementasi OOP. Saya menulis di Jawa untuk beberapa waktu, dan saya harus mengatakan bahwa selama ini, mungkin saya pernah meragukan apa
this
sama dengan di tempat tertentu dalam kode. Dalam JavaScript, keraguan semacam itu dapat muncul setiap hari - setidaknya sampai saat Anda mempelajari beberapa aturan sederhana namun tidak jelas.
Kesalahpahaman tentang this
Ada beberapa kesalahpahaman umum tentang kata kunci ini. Saya ingin segera mengusir mereka sebelum saya sampai ke titik.
ini adalah konteks leksikal.Kesan ini sering muncul di kalangan pemula. Tampaknya bagi mereka bahwa
this
adalah objek di mana, seperti properti, semua variabel dalam cakupan ini disimpan. Kesalahpahaman ini bermula dari fakta bahwa dalam satu kasus tertentu, secara kasar, memang demikian. Jika kita berada di level tertinggi, maka
this
sama dengan
window
(dalam hal skrip biasa di browser). Dan seperti yang kita ketahui, semua variabel yang dideklarasikan di tingkat atas tersedia sebagai properti
window
.
Secara umum, ini tidak benar. Ini mudah diverifikasi.
function test(){ const a = " , "; console.log(this.a); } test();
ini adalah objek yang dimiliki metode iniSekali lagi, ini benar dalam banyak kasus tertentu, tetapi tidak selalu. Yang penting adalah bagaimana fungsi dipanggil, dan bukan apakah itu adalah properti dari beberapa objek. Ini dapat dimengerti bahkan dari logika yang sangat sederhana: anggap fungsi yang sama adalah properti dari dua objek secara bersamaan.
const f = function(){ console.log(this); } const object1 = { method: f }; const object2 = { method: f };
Jadi benda mana yang akan menjadi miliknya ini?
Penting! Bahkan jika suatu objek dibuat menggunakan kelas ES6, ini tidak menjamin sama sekali bahwa metodenya akan selalu memiliki
this
. Jangan tertipu oleh kemiripan dengan kelas dari bahasa "normal".
ini adalah teknik Jedi yang, sekali dipelajari, perlu digunakan di mana-manaSebaiknya hindari penggunaan
this
jika memungkinkan. Satu-satunya kasus ketika sepenuhnya dibenarkan adalah OOP. Di tempat lain, menggunakan
this
bukan hanya jahat, tetapi biasanya terlalu banyak membingungkan kode. Pada dasarnya,
this
adalah argumen tambahan, “minus yang pertama” pada fungsi, yang diteruskan ke sana dengan cara yang rumit dan tidak jelas bagi pemula. Dengan probabilitas tinggi, itu bisa digantikan oleh argumen yang biasa, dan itu hanya akan menjadi lebih baik.
Cara menentukan nilai ini
Di sini saya akan mencoba untuk memberikan algoritma yang ketat dan ringkas yang bahkan seorang programmer yang tidak berpengalaman akan dapat memahami apa yang sama dengan ini dalam kasus khusus. Penjelasan lebih verbal akan disembunyikan di bawah spoiler, sehingga tidak mengacaukan ruang visual.
- Apakah kita di dalam suatu fungsi?
- Ya: lihat item berikutnya.
- Tidak:
this
sama dengan objek global .
KomentarDalam kode tingkat atas (tidak di dalam fungsi apa pun), this
selalu merujuk ke objek global. Dalam kasus skrip reguler di browser, ini adalah objek window
. Tetapi secara umum, ada kasus yang berbeda.
- Apakah kita di dalam fungsi panah?
- Ya: nilai
this
sama dengan di fungsi satu tingkat lebih tinggi (mis. Yang berisi ini). Kembali ke langkah sebelumnya dan ulangi algoritme untuknya. Jika fungsi tidak terkandung dalam yang lain, this
adalah objek global. - Tidak: lihat paragraf berikutnya.
KomentarSalah satu fitur utama fungsi panah adalah apa yang disebut "leksikal this
". Ini berarti bahwa nilai this
dalam fungsi panah ditentukan semata-mata oleh di mana (dalam konteks leksikal apa) itu dibuat, dan tidak bergantung pada bagaimana ia selanjutnya disebut. Terkadang ini bukan yang kita butuhkan, tetapi lebih sering membuat fungsi panah sangat mudah dan dapat diprediksi.
- Apakah fungsi ini disebut sebagai konstruktor (menggunakan operator baru)?
- Ya:
this
merujuk ke objek baru yang "sedang dibangun". - Tidak: lihat paragraf berikutnya.
KomentarMungkin ada baiknya secara terpisah menentukan kasus ketika datang ke konstruktor dari kelas ES6 yang diwarisi. Kemudian, sebelum memanggil super()
, this
tidak memiliki nilai (mengaksesnya akan menyebabkan kesalahan), dan setelah memanggil super()
itu sama dengan objek baru dari kelas induk.
- Apakah fungsi ini dibuat menggunakan bind ?
- Ya: nilai
this
sama dengan nilai argumen pertama yang kami sampaikan ke metode bind
saat membuat fungsi ini. - Tidak: lihat paragraf berikutnya.
KomentarMetode bind
membuat salinan fungsi, memperbaikinya dan, opsional, beberapa argumen pertama untuk itu. Bahkan, ini menciptakan tidak hanya salinan fungsi, tetapi, saya kutip, "objek BoundFunction eksotis". Eksotismenya dimanifestasikan, khususnya, di mana oleh seruan berulang untuk bind
kita tidak bisa lagi mengubah this
. Oleh karena itu, secara tegas, jawaban dalam paragraf ini harus dirumuskan sebagai berikut: jika demikian, maka this
sama dengan argumen pertama dari panggilan pertama untuk bind
, yang mengarah pada penciptaan fungsi ini.
- Apakah fungsi ini disahkan di suatu tempat sebagai panggilan balik atau penangan?
- Ya: Tuhan sendiri yang tahu apa yang akan sama dengan ini ketika dipanggil. Baca dokumentasi untuk hal yang menyebabkannya.
- Tidak: lihat paragraf berikutnya.
KomentarUntuk fungsi non-panah dan terikat, nilai
this
tergantung pada keadaan di mana ia dipanggil. Jika Anda tidak menyebutnya secara pribadi, tetapi meneruskannya di suatu tempat, maka nilai
this
dapat atau tidak dapat diganti dengan nilai yang tidak diketahui untuk Anda.
Contoh:
`use strict` document.addEventListener('keydown', function(){ console.log(this); });
- Fungsi ini disebut menggunakan apply atau call ?
- Ya: dalam hal ini,
this
sama dengan argumen pertama yang diteruskan ke metode yang sesuai. - Tidak: lihat paragraf berikutnya.
KomentarCara lain untuk mengatur this
secara eksplisit. Lebih tepatnya, dua. Namun, dalam hal this
ada perbedaan antara apply
dan call
, satu-satunya perbedaan adalah bagaimana sisa argumen dilewatkan.
- Apakah fungsi ini diperoleh sebagai nilai properti objek dan segera dipanggil?
- Ya:
this
sama dengan objek di atas. - Tidak: lihat paragraf berikutnya.
KomentarSebenarnya, dari mekanisme ini (dan juga dari pengalaman bekerja dengan bahasa lain) kaki tumbuh kepercayaan bahwa "
this
adalah objek yang metodenya kita namakan." Mungkin saya hanya akan menulis kodenya.
'use strict'; const object1 = { method: function(){ console.log(this); } } const object2 = { method: object1.method } object1.method();
- Apakah kode dijalankan dalam mode ketat? ('gunakan ketat', modul ES6)
- Ya:
this
sama dengan undefined
. - Tidak:
this
sama dengan objek global.
KomentarJika kita sampai pada titik ini, maka
this
tidak diatur oleh mekanisme yang memungkinkannya diatur. Ada berbagai kesalahpahaman tentang bagaimana hal ini dapat ditularkan. Misalnya, selama wawancara mereka sering mengatakan hal seperti itu kepada saya:
const obj = { test: function(){ (function(){ console.log(this); })();
Atau, seperti yang saya katakan di bagian "kesalahpahaman", banyak orang berpikir bahwa jika suatu fungsi adalah metode objek yang dibuat menggunakan kelas ES6, maka ini akan selalu sama dengan objek ini di dalamnya. Ini juga tidak benar.
Jadi, jika kita sampai pada titik ini, maka keadaan lain memanggil fungsi kita tidak masalah. Dan semuanya bermuara pada apakah kita dalam mode ketat atau tidak.
Secara historis, sebagai "default"
this
, objek global diteruskan ke fungsi tersebut. Pendekatan ini kemudian diakui sebagai tidak aman. ES5 memperkenalkan mode ketat yang memperbaiki banyak masalah dari versi ECMAScript sebelumnya. Itu disertakan dengan arahan 'gunakan ketat' di awal file atau fungsi. Dalam mode ini, nilai "default"
this
tidak
undefined
.
Dalam modul ES6, mode ketat diaktifkan secara default.
Ada juga mekanisme lain untuk memasukkan mode ketat, misalnya, di NodeJS, mode ketat untuk semua file dapat diaktifkan dengan
--use-strict
.
Itu, secara umum, itu saja. Menentukan nilai
this
, tentu saja, tidak sesederhana yang kita inginkan, tetapi tidak sesulit kelihatannya. Pelajari algoritma ini sebagai tabel perkalian - dan Anda tidak akan pernah mengalami masalah dengan
this
lagi. Hal-hal seperti itu.
Pengguna PS
Aingis menyarankan bahwa ketika menggunakan
dengan konstruksi, objek yang diteruskan ke dalamnya sebagai konteks menggantikan objek global. Mungkin saya tidak akan memasukkan ini ke dalam classifier saya, karena kesempatan untuk bertemu di 2019+ agak kecil. Tetapi bagaimanapun juga, ini adalah hal yang menarik.
Pengguna PPS,
rqrqrqrq, menyarankan bahwa yang
new
prioritas lebih tinggi daripada yang
bind
. Revisi yang sesuai untuk classifier telah dibuat. Terima kasih