Memahami Penutupan JavaScript dalam Gelung: Contoh Praktikal

JavaScript

Membongkar Penutupan Gelung dalam JavaScript

Pembangun JavaScript sering menghadapi tingkah laku yang tidak dijangka apabila menggunakan penutupan dalam gelung. Masalah ini boleh menimbulkan kekeliruan terutama bagi mereka yang baru mengenali konsep penutupan.

Dalam artikel ini, kami akan meneroka contoh praktikal yang menggambarkan perangkap biasa dan menyediakan penyelesaian untuk menggunakan penutupan secara berkesan dalam gelung, sama ada berurusan dengan pendengar acara, kod tak segerak atau mengulang tatasusunan.

Perintah Penerangan
let Mengisytiharkan pembolehubah tempatan berskop blok, secara pilihan memulakannya kepada nilai. Digunakan untuk memastikan setiap lelaran gelung mempunyai skopnya sendiri.
const Mengisytiharkan pemalar berskop blok, baca sahaja yang dinamakan. Digunakan untuk mencipta fungsi atau pembolehubah yang nilainya tidak boleh berubah.
Promise Mewakili penyiapan akhirnya (atau kegagalan) operasi tak segerak dan nilai yang terhasil.
setTimeout Memanggil fungsi atau menilai ungkapan selepas bilangan milisaat tertentu.
addEventListener Melampirkan pengendali acara pada elemen tertentu tanpa menulis ganti pengendali acara sedia ada.
IIFE Ungkapan Fungsi Dipanggil Serta-merta. Fungsi yang berjalan sebaik sahaja ia ditakrifkan. Digunakan untuk mencipta skop tempatan dalam gelung.
for...in Mengulangi sifat objek yang boleh dikira, dalam susunan sewenang-wenangnya.
for...of Mengulang nilai objek boleh lelaran (seperti tatasusunan atau rentetan), dalam susunan tertentu.

Memahami Penutupan JavaScript dalam Gelung

Skrip yang disediakan dalam contoh sebelumnya menangani isu umum penutupan dalam gelung dalam JavaScript. Apabila menggunakan a pengisytiharan dalam gelung, semua lelaran berkongsi skop fungsi yang sama. Inilah sebabnya, dalam contoh pertama, output ialah "Nilai saya: 3" tiga kali. Penyelesaiannya adalah dengan menggunakan , yang mencipta skop blok yang mengekalkan nilai yang betul untuk setiap lelaran. Pendekatan ini memastikan bahawa setiap lelaran mempunyai skopnya sendiri, dengan itu mengekalkan nilai yang betul apabila fungsi dipanggil. Skrip menunjukkan cara menukar perisytiharan daripada kepada let membetulkan isu dan log "Nilai saya: 0", "Nilai saya: 1", dan "Nilai saya: 2" seperti yang dimaksudkan.

Untuk kod tak segerak, isu penutupan yang sama boleh timbul. menggunakan dan berfungsi dengan memastikan bahawa setiap panggilan tak segerak mengekalkan nilai lelaran yang betul. Skrip menunjukkan bahawa dengan menggunakan wait dengan , setiap janji yang diselesaikan mencatatkan nilai yang dijangkakan. Pendengar acara juga boleh menghadapi isu yang sama; walau bagaimanapun, membungkus fungsi pendengar dalam an (Ungkapan Fungsi Dipanggil Serta-merta) membantu menangkap nilai yang betul dengan mencipta skop baharu untuk setiap lelaran. Penggunaan dan for...of gelung seterusnya menunjukkan kepentingan skop dalam penutupan, mempamerkan cara menangkap indeks dan nilai dengan betul menggunakan untuk mencipta skop yang berbeza untuk setiap lelaran gelung.

Menyelesaikan Isu Penutupan dalam Gelung JavaScript dengan let

JavaScript (ES6)

let funcs = [];
// Let's create 3 functions
for (let i = 0; i < 3; i++) {
  // and store them in funcs
  funcs[i] = function() {
    // each should log its value.
    console.log("My value:", i);
  };
}
for (let j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}

Memastikan Nilai Penutupan yang Betul dalam Kod Asynchronous

JavaScript (ES6)

const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));
for (let i = 0; i < 3; i++) {
  // Log `i` as soon as each promise resolves.
  wait(i * 100).then(() => console.log(i));
}

Penutupan Betul dalam Pendengar Acara Menggunakan IIFE

JavaScript (ES6)

var buttons = document.getElementsByTagName("button");
// Let's create 3 functions
for (var i = 0; i < buttons.length; i++) {
  // as event listeners
  (function(i) {
    buttons[i].addEventListener("click", function() {
      // each should log its value.
      console.log("My value:", i);
    });
  })(i);
}

Penutupan Betul dengan untuk...dalam dan untuk...gelung

JavaScript (ES6)

const arr = [1, 2, 3];
const fns = [];
for (const i in arr) {
  fns.push(((i) => () => console.log("index:", i))(i));
}
for (const v of arr) {
  fns.push(((v) => () => console.log("value:", v))(v));
}
for (const n of arr) {
  const obj = { number: n };
  fns.push(((n, obj) => () => console.log("n:", n, "|", "obj:", JSON.stringify(obj)))(n, obj));
}
for (const f of fns) {
  f();
}

Meneroka Penggunaan Penutupan dalam Fungsi JavaScript Lanjutan

Penutupan ialah konsep asas dalam JavaScript yang membenarkan fungsi mengakses pembolehubah daripada skop lampirannya, walaupun selepas skop itu ditutup. Ciri ini amat berkuasa apabila mencipta fungsi lanjutan seperti yang digunakan dalam penghafalan, kari dan pengaturcaraan berfungsi. Sebagai contoh, penghafalan memanfaatkan penutupan untuk mengingati hasil panggilan fungsi yang mahal dan mengembalikan hasil cache apabila input yang sama berlaku lagi. Dengan menggunakan penutupan, kami boleh mencipta kod yang lebih cekap dan dioptimumkan yang meningkatkan prestasi, terutamanya dalam fungsi rekursif seperti mengira jujukan Fibonacci.

Satu lagi penggunaan lanjutan penutupan adalah dalam mencipta pembolehubah dan fungsi peribadi dalam objek JavaScript, mensimulasikan kaedah dan sifat peribadi. Teknik ini sering digunakan dalam corak modul dan menggunakan ekspresi fungsi (IIFE) serta-merta untuk merangkum fungsi dan mengelakkan pencemaran skop global. Selain itu, penutupan memainkan peranan penting dalam pengendalian acara dan pengaturcaraan tak segerak, yang membantu mengekalkan keadaan dan konteks dari semasa ke semasa. Memahami dan menggunakan penutupan secara berkesan boleh meningkatkan kemahiran pengaturcaraan JavaScript anda dengan ketara dan membolehkan anda menulis kod yang lebih modular, boleh digunakan semula dan boleh diselenggara.

  1. Apakah penutupan dalam JavaScript?
  2. Penutupan ialah fungsi yang mengekalkan akses kepada skop leksikalnya, walaupun apabila fungsi itu dilaksanakan di luar skop tersebut.
  3. Mengapa penutupan berlaku dalam gelung?
  4. Penutupan dalam gelung berlaku kerana gelung mencipta fungsi yang menangkap rujukan pembolehubah yang sama, membawa kepada tingkah laku yang tidak dijangka jika tidak dikendalikan dengan betul.
  5. Bagaimanakah kita boleh membetulkan isu penutupan dalam gelung?
  6. menggunakan bukannya dalam gelung atau menggunakan (Ungkapan Fungsi Yang Dikenakan Serta-merta) boleh membetulkan isu penutupan dengan mencipta skop baharu untuk setiap lelaran.
  7. Apakah itu IIFE?
  8. An ialah fungsi yang dilaksanakan sejurus selepas ia dicipta, selalunya digunakan untuk mencipta skop baharu dan mengelakkan konflik berubah.
  9. Bolehkah penutupan digunakan dalam pengaturcaraan tak segerak?
  10. Ya, penutupan adalah penting dalam pengaturcaraan tak segerak untuk mengekalkan keadaan dan konteks merentas operasi tak segerak seperti janji dan panggil balik.
  11. Apakah penghafalan, dan bagaimana penutupan membantu?
  12. Memoisasi ialah teknik pengoptimuman untuk cache hasil panggilan fungsi yang mahal. Penutupan membantu dengan mengekalkan akses kepada cache merentas berbilang panggilan fungsi.
  13. Bagaimanakah penutupan membantu dalam pengendalian acara?
  14. Penutupan mengekalkan keadaan pembolehubah yang diperlukan oleh pengendali acara, memastikan ia berfungsi dengan betul apabila peristiwa dicetuskan.
  15. Apakah corak modul dalam JavaScript?
  16. Corak modul menggunakan penutupan untuk mencipta pembolehubah dan fungsi persendirian, merangkum fungsi dan mengelakkan pencemaran skop global.
  17. Bolehkah penutupan mensimulasikan kaedah peribadi dalam JavaScript?
  18. Ya, penutupan boleh mensimulasikan kaedah persendirian dengan memastikan pembolehubah dan fungsi boleh diakses hanya dalam skop fungsi yang ditakrifkan.

Menguasai penutupan dalam JavaScript, terutamanya dalam gelung, adalah penting untuk menulis kod yang boleh diramal dan cekap. Dengan memanfaatkan , , dan , pembangun boleh mengelakkan perangkap biasa dan memastikan skop pembolehubah yang betul. Pemahaman ini meningkatkan keupayaan untuk mengendalikan tugas tak segerak dan pengaturcaraan dipacu peristiwa, akhirnya membawa kepada aplikasi yang lebih mantap.