Kata kunci ini dalam JavaScript. Lengkap * manual

* Kemungkinan besar, saya melewatkan sesuatu, tetapi saya yakin komentar akan mengatakan ini kepada saya

Saya 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.

gambar

Konten

  1. Pendahuluan
  2. Kesalahpahaman tentang ini
  3. 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 ini

Sekali 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-mana

Sebaiknya 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.

  1. Apakah kita di dalam suatu fungsi?

    • Ya: lihat item berikutnya.
    • Tidak: this sama dengan objek global .

    Komentar
    Dalam 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.
  2. 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.

    Komentar
    Salah 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.
  3. Apakah fungsi ini disebut sebagai konstruktor (menggunakan operator baru)?

    • Ya: this merujuk ke objek baru yang "sedang dibangun".
    • Tidak: lihat paragraf berikutnya.

    Komentar
    Mungkin 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.
  4. 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.

    Komentar
    Metode 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.
  5. 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.

    Komentar
    Untuk 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); }); //    this === document.    DOM- this  currentTarget [1, 2, 3].forEach(function(){ console.log(this); }); //         ,  undefined. ?     . 
  6. 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.

    Komentar
    Cara 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.
  7. Apakah fungsi ini diperoleh sebagai nilai properti objek dan segera dipanggil?

    • Ya: this sama dengan objek di atas.
    • Tidak: lihat paragraf berikutnya.

    Komentar
    Sebenarnya, 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(); //    object1 -           object1['method'](); //  .        object2.method(); //    object2 -  " ",      ,         
  8. Apakah kode dijalankan dalam mode ketat? ('gunakan ketat', modul ES6)

    • Ya: this sama dengan undefined .
    • Tidak: this sama dengan objek global.

    Komentar
    Jika 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); })(); //      } } obj.test(); //  ,     obj.   

    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

Source: https://habr.com/ru/post/id464163/


All Articles