Demystifying JavaScript Closures, Callbacks and Iifes
mata teras
- penutupan JavaScript adalah fungsi yang boleh mengakses pembolehubah skop induk mereka.
- Fungsi panggil balik adalah fungsi yang diluluskan sebagai parameter kepada fungsi lain, yang kemudian dilaksanakan dalam fungsi luaran, menyediakan cara untuk melambatkan pelaksanaan atau mengekalkan perintah operasi tak segerak.
- Melaksanakan Ekspresi Fungsi Sekarang (Iife) adalah fungsi yang dilaksanakan dengan segera selepas definisi untuk melindungi skop pembolehubah dan mencegah pencemaran skop global.
- Penutupan boleh membaca dan mengemas kini pembolehubah yang disimpan dalam skop mereka, dan kemas kini ini dapat dilihat oleh sebarang penutupan yang mengakses pembolehubah ini, yang membuktikan bahawa penutupan kedai merujuk kepada pembolehubah, dan bukan nilai.
- Menggunakan IIFE membantu membuat skop peribadi dalam fungsi, dengan itu menguruskan pembolehubah dengan lebih baik dan menghalang akses luaran ke pembolehubah ini.
- Gabungan konsep -konsep ini (penutupan, fungsi panggil balik, dan IIFE) menyediakan alat yang berkuasa untuk menulis kod JavaScript ringkas, cekap dan selamat untuk merangkum fungsi dan mengelakkan pencemaran skop global.
Penutup
Dalam JavaScript, penutupan adalah sebarang fungsi yang mengekalkan rujukan kepada pemboleh ubah skop induknya, walaupun fungsi induk telah kembali. Sebenarnya, sebarang fungsi boleh dianggap sebagai penutupan, kerana seperti yang kita pelajari dalam bahagian Skop Variabel dari bahagian pertama tutorial ini, fungsi boleh dirujuk atau diakses:
Sebarang pembolehubah dan parameter dalam skop fungsi sendiri
- Sebarang pembolehubah dan parameter fungsi luaran (induk)
- Sebarang pemboleh ubah dalam skop global
- jadi anda mungkin telah menggunakan penutupan tanpa mengetahui. Tetapi matlamat kami bukan hanya untuk menggunakannya -tetapi untuk memahami mereka. Jika kita tidak faham bagaimana mereka berfungsi, kita tidak boleh menggunakannya dengan betul. Untuk melakukan ini, kami memecahkan definisi penutupan di atas ke tiga perkara utama yang mudah difahami.
Point 1: Anda boleh merujuk kepada pembolehubah yang ditakrifkan di luar fungsi semasa.
Dalam contoh kod ini, fungsi merujuk kepada parameter pembolehubah dan
fungsi yang tertutup (induk)function setLocation(city) { var country = "France"; function printLocation() { console.log("You are in " + city + ", " + country); } printLocation(); } setLocation("Paris"); // 输出:You are in Paris, France
dipanggil, printLocation()
berjaya mengeluarkan "anda berada di Paris, Perancis" menggunakan bekas pembolehubah dan parameter. setLocation()
country
Point 2: city
Fungsi dalaman boleh merujuk kepada pembolehubah yang ditakrifkan dalam fungsi luaran walaupun selepas fungsi luaran pulangan. setLocation()
printLocation()
function setLocation(city) { var country = "France"; function printLocation() { console.log("You are in " + city + ", " + country); } printLocation(); } setLocation("Paris"); // 输出:You are in Paris, France
Ini hampir sama dengan contoh pertama, kecuali kali ini printLocation()
kembali dalam di luar fungsi setLocation()
, dan bukannya memanggil segera. Oleh itu, nilai currentLocation
adalah fungsi dalaman printLocation()
.
Jika kita mengingatkan seperti ini currentLocation
- alert(currentLocation);
- kita akan mendapat output berikut:
function setLocation(city) { var country = "France"; function printLocation() { console.log("You are in " + city + ", " + country); } return printLocation; } var currentLocation = setLocation("Paris"); currentLocation(); // 输出:You are in Paris, France
seperti yang telah kita lihat, printLocation()
dilaksanakan di luar skop leksikalnya. setLocation()
nampaknya hilang, tetapi printLocation()
masih boleh mengakses dan "ingat" pembolehubahnya (country
) dan parameter (city
).
Penutupan (fungsi dalaman) dapat mengingati skop di sekelilingnya (fungsi luaran) walaupun ia dilaksanakan di luar skop leksikalnya. Oleh itu, anda boleh memanggilnya pada bila -bila masa dalam program anda.
Point 3: fungsi dalaman menyimpan pembolehubah yang berfungsi luaran dengan rujukan, dan bukannya dengan nilai.
function printLocation () { console.log("You are in " + city + ", " + country); }
di sini cityLocation()
Mengembalikan objek yang mengandungi dua penutupan- get()
dan set()
-berkali merujuk kepada pembolehubah luaran city
. get()
Dapatkan nilai semasa city
dan set()
mengemas kini. Apabila panggilan kedua myLocation.get()
, ia mengeluarkan nilai terkini (semasa) city
- "Sydney" - bukannya "Paris" lalai.
daripada menyalin nilainya. Ini adalah titik yang sangat penting, kerana tidak mengetahui ini boleh membawa kepada beberapa kesilapan logik yang sukar dicari-seperti yang akan kita lihat dalam seksyen "melaksanakan ekspresi fungsi segera (Iife)". Ciri menarik penutupan ialah pembolehubah dalam penutupan secara automatik tersembunyi. Penutupan menyimpan data dalam pembolehubah tertutup tanpa menyediakan cara untuk mengaksesnya secara langsung. Satu -satunya cara untuk mengubah pembolehubah ini adalah untuk mengaksesnya secara tidak langsung. Sebagai contoh, dalam coretan kod terakhir, kita melihat bahawa kita hanya boleh secara tidak langsung mengubah suai pembolehubah
dengan menggunakan penutupan dan get()
. set()
city
kita boleh menggunakan tingkah laku ini untuk menyimpan data peribadi dalam objek. Daripada menyimpan data sebagai sifat objek, simpannya sebagai pembolehubah dalam pembina dan kemudian gunakan penutupan sebagai cara untuk merujuk pembolehubah tersebut.
Seperti yang anda lihat, tidak ada yang misteri atau mendalam di sekitar penutupan -hanya tiga mata mudah untuk diingat.
Fungsi Callback
Dalam JavaScript, fungsi adalah warga kelas pertama. Salah satu akibat dari fakta ini ialah fungsi boleh diluluskan sebagai hujah kepada fungsi lain atau dikembalikan oleh fungsi lain.
Fungsi yang mengambil fungsi lain sebagai parameter atau fungsi pulangan kerana hasilnya dipanggil fungsi pesanan lebih tinggi, dan fungsi yang diluluskan sebagai parameter dipanggil fungsi panggil balik. Ia dipanggil "panggilan balik" kerana pada satu ketika, ia akan menjadi "panggil balik" dengan fungsi pesanan yang lebih tinggi.
Fungsi panggil balik mempunyai banyak kegunaan harian. Salah satu daripada mereka adalah apabila kita menggunakan kaedah setTimeout()
dan setInterval()
objek tetingkap pelayar - kaedah ini menerima dan melaksanakan fungsi panggilan balik:
function setLocation(city) { var country = "France"; function printLocation() { console.log("You are in " + city + ", " + country); } printLocation(); } setLocation("Paris"); // 输出:You are in Paris, France
Satu lagi contoh ialah apabila kita melampirkan pendengar acara ke elemen pada halaman. Dengan melakukan ini, kami sebenarnya memberikan penunjuk kepada fungsi panggil balik, yang akan dipanggil apabila peristiwa berlaku.
function setLocation(city) { var country = "France"; function printLocation() { console.log("You are in " + city + ", " + country); } return printLocation; } var currentLocation = setLocation("Paris"); currentLocation(); // 输出:You are in Paris, France
Cara paling mudah untuk memahami bagaimana fungsi pesanan dan fungsi panggil balik yang lebih tinggi berfungsi adalah untuk mewujudkan fungsi pesanan tinggi dan fungsi panggilan balik anda sendiri. Jadi, mari buat sekarang:
function printLocation () { console.log("You are in " + city + ", " + country); }
di sini kita membuat fungsi fullName()
, yang menerima tiga parameter - dua untuk nama pertama dan terakhir, dan satu untuk fungsi panggilan balik. Kemudian, selepas pernyataan console.log()
, kami meletakkan panggilan fungsi yang akan mencetuskan fungsi panggil balik sebenar -fungsi fullName()
yang ditakrifkan di bawah greeting()
. Akhirnya, kami memanggil fullName()
di mana greeting()
diluluskan sebagai pemboleh ubah- tanpa kurungan -memberikannya kita tidak mahu ia dilaksanakan dengan segera, tetapi hanya mahu menunjuknya untuk kegunaan kemudian oleh fullName()
.
Kami melewati definisi fungsi, bukan fungsi panggilan. Ini menghalang fungsi panggil balik daripada dilaksanakan dengan serta -merta, yang tidak konsisten dengan falsafah di sebalik fungsi panggilan balik. Diluluskan sebagai definisi fungsi, mereka boleh dilaksanakan pada bila -bila masa dan pada bila -bila masa dalam fungsi yang mengandungi. Selain itu, kerana fungsi panggil balik berkelakuan seperti mereka sebenarnya diletakkan di dalam fungsi, mereka sebenarnya menutup: mereka boleh mengakses pembolehubah dan parameter yang mengandungi fungsi, dan juga mengakses pembolehubah dalam skop global.
Fungsi panggil balik boleh menjadi fungsi yang ada (seperti yang ditunjukkan dalam contoh sebelumnya) atau fungsi tanpa nama.
function cityLocation() { var city = "Paris"; return { get: function() { console.log(city); }, set: function(newCity) { city = newCity; } }; } var myLocation = cityLocation(); myLocation.get(); // 输出:Paris myLocation.set('Sydney'); myLocation.get(); // 输出:Sydney
Katakan kita memerlukan dua fungsi - satu yang mencetak maklumat artikel yang diterbitkan dan yang lain yang mencetak maklumat mesej yang dihantar. Kami mencipta mereka, tetapi kami perhatikan bahawa sebahagian daripada logik kami diulang dalam kedua -dua fungsi. Kami tahu bahawa mempunyai kod yang sama di satu tempat tidak perlu dan sukar untuk dijaga. Jadi, apakah penyelesaiannya? Mari kita gambarkannya dalam contoh seterusnya:
function setLocation(city) { var country = "France"; function printLocation() { console.log("You are in " + city + ", " + country); } printLocation(); } setLocation("Paris"); // 输出:You are in Paris, France
Apa yang kita lakukan di sini adalah meletakkan corak kod pendua (console.log(item)
dan var date = new Date()
) ke dalam fungsi umum yang berasingan (publish()
) dan hanya menyimpan data khusus dalam fungsi lain - fungsi ini kini menjadi fungsi panggilan balik. Dengan cara ini, menggunakan fungsi yang sama, kita boleh mencetak maklumat yang relevan mengenai pelbagai perkara yang berkaitan - mesej, artikel, buku, majalah, dll. Satu -satunya perkara yang perlu anda lakukan ialah membuat fungsi panggil balik khas untuk setiap jenis dan lulus sebagai hujah kepada fungsi publish()
.
Jalankan ekspresi fungsi dengan segera (iife)
Jalankan ekspresi fungsi dengan segera, atau Iife (disebut "ify"), adalah ungkapan fungsi (dinamakan atau tanpa nama) yang dilaksanakan dengan segera selepas ia dibuat.
Terdapat dua varian sintaks yang sedikit berbeza dalam mod ini:
function setLocation(city) { var country = "France"; function printLocation() { console.log("You are in " + city + ", " + country); } return printLocation; } var currentLocation = setLocation("Paris"); currentLocation(); // 输出:You are in Paris, France
Untuk menukar fungsi biasa ke Iife, anda perlu melakukan dua langkah:
- Anda perlu melampirkan keseluruhan fungsi dalam kurungan. Seperti namanya, Iife mestilah ungkapan fungsi, bukan definisi fungsi. Oleh itu, tujuan melampirkan kurungan adalah untuk menukar definisi fungsi menjadi ungkapan. Ini kerana dalam JavaScript segala -galanya dalam kurungan dianggap sebagai ungkapan.
- anda perlu menambah sepasang kurungan pada akhir (variasi 1), atau selepas menutup pendakap (variasi 2), yang menyebabkan fungsi dilaksanakan dengan segera.
Tiga lagi perkara yang perlu diingat:
Pertama sekali, jika anda memberikan fungsi kepada pemboleh ubah, anda tidak perlu melampirkan keseluruhan fungsi dalam kurungan, kerana ia sudah menjadi ungkapan:
function printLocation () { console.log("You are in " + city + ", " + country); }
Kedua, IIFE berakhir dengan titik koma, jika tidak, kod anda mungkin tidak berfungsi dengan baik.
ketiga, anda boleh lulus parameter ke Iife (ia adalah fungsi selepas semua), seperti yang ditunjukkan dalam contoh berikut:
function cityLocation() { var city = "Paris"; return { get: function() { console.log(city); }, set: function(newCity) { city = newCity; } }; } var myLocation = cityLocation(); myLocation.get(); // 输出:Paris myLocation.set('Sydney'); myLocation.get(); // 输出:Sydney
Melewati objek global sebagai parameter kepada IIFE adalah corak yang sama untuk mengaksesnya di dalam fungsi tanpa menggunakan objek window
, yang menjadikan kod bebas dari persekitaran penyemak imbas. Kod berikut mencipta pembolehubah global
yang akan merujuk objek global tidak kira platform apa yang anda gunakan:
function showMessage(message) { setTimeout(function() { alert(message); }, 3000); } showMessage('Function called 3 seconds ago');
Kod ini berfungsi dalam penyemak imbas (objek global adalah window
) atau dalam persekitaran Node.js (kami menggunakan pembolehubah khas global
untuk merujuk kepada objek global).
Salah satu manfaat besar IIFE ialah apabila menggunakannya, anda tidak perlu bimbang tentang mencemarkan ruang global dengan pembolehubah sementara. Semua pembolehubah yang anda tentukan di dalam Iife akan menjadi tempatan. Mari kita periksa:
<!-- HTML --> <button id="btn">Click me</button> <!-- JavaScript --> function showMessage() { alert('Woohoo!'); } var el = document.getElementById("btn"); el.addEventListener("click", showMessage);
Dalam contoh ini, pernyataan pertama console.log()
berfungsi dengan baik, tetapi pernyataan kedua gagal kerana pembolehubah today
dan currentTime
menjadi pembolehubah tempatan kerana IIFE.
Kami sudah tahu bahawa penutupan mengekalkan rujukan kepada pembolehubah luaran, jadi mereka mengembalikan nilai terkini/terkini. Jadi, apa yang anda fikir adalah output contoh berikut?
function setLocation(city) { var country = "France"; function printLocation() { console.log("You are in " + city + ", " + country); } printLocation(); } setLocation("Paris"); // 输出:You are in Paris, France
Anda mungkin mengharapkan nama buah itu dicetak satu demi satu pada selang saat. Walau bagaimanapun, sebenarnya, output adalah empat kali "undefined". Jadi, apa masalahnya?
Masalahnya ialah dalam pernyataan, nilai console.log()
sama dengan 4 untuk setiap lelaran gelung. Dan, kerana kita tidak mempunyai apa -apa pada pengindeksan 4 dalam array i
, output adalah "undefined". (Ingat, dalam JavaScript, indeks array bermula pada 0.) Apabila fruits
sama dengan 4, gelung itu berakhir. i
. Kami melakukan ini dengan mematikan kaedah i
dalam IIFE dan menentukan pemboleh ubah peribadi untuk memegang salinan semasa setTimeout()
. i
function setLocation(city) { var country = "France"; function printLocation() { console.log("You are in " + city + ", " + country); } return printLocation; } var currentLocation = setLocation("Paris"); currentLocation(); // 输出:You are in Paris, France
function printLocation () { console.log("You are in " + city + ", " + country); }
Kesimpulan
Tujuan tutorial ini adalah untuk memperkenalkan konsep -konsep asas ini dengan jelas dan ringkas mungkin -sebagai satu set prinsip atau peraturan yang mudah. Pemahaman yang baik tentang mereka adalah kunci untuk menjadi pemaju JavaScript yang berjaya dan cekap.Untuk menerangkan topik yang dibentangkan di sini dengan lebih terperinci dan mendalam, saya cadangkan anda membaca "Anda Tidak Tahu JS: Skop dan Penutupan" oleh Kyle Simpson.
(Kandungan berikutnya, iaitu bahagian FAQ, telah ditinggalkan kerana panjang artikel. Jika perlu, sila tanya soalan tertentu.)
Atas ialah kandungan terperinci Demystifying JavaScript Closures, Callbacks and Iifes. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Soalan dan penyelesaian yang sering ditanya untuk percetakan tiket kertas terma depan dalam pembangunan front-end, percetakan tiket adalah keperluan umum. Walau bagaimanapun, banyak pemaju sedang melaksanakan ...

JavaScript adalah asas kepada pembangunan web moden, dan fungsi utamanya termasuk pengaturcaraan yang didorong oleh peristiwa, penjanaan kandungan dinamik dan pengaturcaraan tak segerak. 1) Pengaturcaraan yang didorong oleh peristiwa membolehkan laman web berubah secara dinamik mengikut operasi pengguna. 2) Penjanaan kandungan dinamik membolehkan kandungan halaman diselaraskan mengikut syarat. 3) Pengaturcaraan Asynchronous memastikan bahawa antara muka pengguna tidak disekat. JavaScript digunakan secara meluas dalam interaksi web, aplikasi satu halaman dan pembangunan sisi pelayan, sangat meningkatkan fleksibiliti pengalaman pengguna dan pembangunan silang platform.

Tidak ada gaji mutlak untuk pemaju Python dan JavaScript, bergantung kepada kemahiran dan keperluan industri. 1. Python boleh dibayar lebih banyak dalam sains data dan pembelajaran mesin. 2. JavaScript mempunyai permintaan yang besar dalam perkembangan depan dan stack penuh, dan gajinya juga cukup besar. 3. Faktor mempengaruhi termasuk pengalaman, lokasi geografi, saiz syarikat dan kemahiran khusus.

Bagaimana cara menggabungkan elemen array dengan ID yang sama ke dalam satu objek dalam JavaScript? Semasa memproses data, kita sering menghadapi keperluan untuk mempunyai id yang sama ...

Pembelajaran JavaScript tidak sukar, tetapi ia mencabar. 1) Memahami konsep asas seperti pembolehubah, jenis data, fungsi, dan sebagainya. 2) Pengaturcaraan asynchronous tuan dan melaksanakannya melalui gelung acara. 3) Gunakan operasi DOM dan berjanji untuk mengendalikan permintaan tak segerak. 4) Elakkan kesilapan biasa dan gunakan teknik debugging. 5) Mengoptimumkan prestasi dan mengikuti amalan terbaik.

Perbincangan mengenai realisasi kesan animasi tatal dan elemen Parallax dalam artikel ini akan meneroka bagaimana untuk mencapai yang serupa dengan laman web rasmi Shiseido (https://www.shiseido.co.jp/sb/wonderland/) ... ...

Trend terkini dalam JavaScript termasuk kebangkitan TypeScript, populariti kerangka dan perpustakaan moden, dan penerapan webassembly. Prospek masa depan meliputi sistem jenis yang lebih berkuasa, pembangunan JavaScript, pengembangan kecerdasan buatan dan pembelajaran mesin, dan potensi pengkomputeran IoT dan kelebihan.

Perbincangan mendalam mengenai punca-punca utama perbezaan dalam output konsol.log. Artikel ini akan menganalisis perbezaan hasil output fungsi Console.log dalam sekeping kod dan menerangkan sebab -sebab di belakangnya. � ...
