Rumah >hujung hadapan web >tutorial js >Pengenalan terperinci kepada penutupan (Penutupan) dalam kemahiran JavaScript_javascript

Pengenalan terperinci kepada penutupan (Penutupan) dalam kemahiran JavaScript_javascript

WBOY
WBOYasal
2016-05-16 16:23:32916semak imbas

Penutupan ialah ciri penting dalam JavaScript Peranan terbesarnya ialah menyimpan maklumat semasa menjalankan fungsi. Dalam JavaScript, banyak ciri penutupan berasal daripada rantai skop semasa panggilan fungsi.

Rantai skop objek panggilan fungsi dan pembolehubah

Untuk setiap panggilan fungsi dalam JavaScript, JavaScript akan mencipta objek setempat untuk menyimpan pembolehubah setempat yang ditakrifkan dalam fungsi jika terdapat fungsi bersarang yang ditakrifkan di dalam fungsi, maka JavaScript akan Menentukan objek tempatan bersarang di atas objek yang sudah ada objek tempatan yang ditentukan. Untuk fungsi, terdapat seberapa banyak lapisan objek tempatan bersarang kerana terdapat lapisan definisi fungsi bersarang di dalamnya. Objek tempatan ini dipanggil "objek panggilan fungsi" ("objek panggilan" dalam ECMAScript 3, dinamakan semula sebagai "rekod persekitaran deklaratif" dalam ECMAScript 5, tetapi secara peribadi saya fikir nama dalam ECMAScript 3 lebih mudah difahami). Ambil panggilan fungsi berikut sebagai contoh:


Salin kod Kod adalah seperti berikut:

fungsi f(x){
var a = 10;
kembalikan a*x;
}
console.log(f(6));//60

Dalam contoh mudah ini, apabila fungsi f() dipanggil, JavaScript akan mencipta objek panggilan bagi fungsi f() (mari kita panggil ia f_invokeObj Terdapat dua atribut di dalam objek f_invokeObj: a dan x; menjalankan f(), nilai a ialah 10 dan nilai x ialah 6, jadi hasil pulangan akhir ialah 60. Ikonnya adalah seperti berikut:

Apabila fungsi bersarang wujud, JavaScript akan mencipta berbilang objek panggilan fungsi:


Salin kod Kod adalah seperti berikut:

fungsi f(x){
var a = 10;
kembalikan a*g(x);
fungsi g(b){
Kembalikan b*b;
}
}
console.log(f(6));//360


Dalam contoh ini, apabila fungsi f() dipanggil, JavaScript akan mencipta objek panggilan (f_invokeObj) bagi fungsi f(), yang mempunyai dua atribut dalaman a dan x Nilai a ialah 10 dan nilai x ialah 6; jalankan f (), JavaScript akan menghuraikan dan mentakrifkan fungsi g() dalam fungsi f(), dan mencipta objek panggilan (g_invokeObj) bagi g(), yang mempunyai atribut dalaman b, dan nilai b ialah sama dengan parameter masuk x, iaitu 6 , jadi hasil pulangan akhir ialah 360. Ikonnya adalah seperti berikut:

Seperti yang anda lihat, objek panggilan fungsi membentuk rantai. Apabila fungsi terbenam g() sedang berjalan dan perlu mendapatkan nilai pembolehubah, carian akan bermula dari objek panggilan fungsi yang terdekat Jika ia tidak boleh dicari, ia akan mencari dalam objek panggilan lanjut di sepanjang rantaian objek panggilan fungsi apa yang dipanggil "rantai skop pembolehubah". Jika pembolehubah yang sama muncul dalam dua objek panggilan fungsi, fungsi akan mengambil nilai pembolehubah dalam objek panggilan yang paling hampir dengan dirinya:


Salin kod Kod adalah seperti berikut:

fungsi f(x){
var a = 10;
Kembalikan a*g(x);
fungsi g(b){
var a = 1;
Kembalikan b*b*a;
}
}
console.log(f(6));//360, bukan 3600


Dalam contoh di atas, pembolehubah a wujud dalam kedua-dua objek panggilan bagi fungsi g() (g_invokeObj) dan objek panggilan bagi fungsi f() (f_invokeObj) dan nilai a adalah berbeza Apabila fungsi g() adalah run, dalam g() Nilai yang digunakan di dalam fungsi ialah 1, manakala nilai yang digunakan di luar fungsi g() ialah 10. Rajah menunjukkan rantai objek panggilan fungsi pada masa ini seperti berikut:

Apakah itu penutupan?

Semua fungsi (fungsi) dalam JavaScript adalah objek, dan apabila fungsi ditakrifkan, rantai objek panggilan fungsi yang sepadan akan dijana Definisi fungsi sepadan dengan rantai objek panggilan fungsi. Selagi objek fungsi wujud, objek panggilan fungsi yang sepadan wujud apabila fungsi tidak lagi digunakan, objek panggilan fungsi yang sepadan akan dikumpul dan gabungan satu-satu antara objek fungsi dan objek panggilan fungsi rantai, Hanya panggil ia "penutupan". Dalam contoh fungsi f() dan fungsi g() di atas, terdapat dua penutupan: objek fungsi f() dan objek f_invokeObj membentuk penutupan, dan objek fungsi g() dan rantai objek g_invokeObj-f_invokeObj membentuk bersama-sama Penutupan kedua. Apabila fungsi g() selesai melaksanakan, penutupan g() dikumpul kerana fungsi g() tidak lagi digunakan kemudian, apabila fungsi f() selesai dilaksanakan, f() ditutup atas sebab yang sama bungkusan itu juga sampah dikutip.

Daripada definisi penutupan, kita boleh membuat kesimpulan bahawa semua fungsi JavaScript adalah penutupan selepas definisi - kerana semua fungsi adalah objek, semua fungsi juga mempunyai rantai objek panggilan yang sepadan selepas pelaksanaan.

Walau bagaimanapun, di mana penutupan benar-benar berlaku adalah dalam kes fungsi bersarang. Oleh kerana fungsi sebaris ditakrifkan apabila fungsi luaran sedang berjalan, nilai pembolehubah yang disimpan dalam penutupan fungsi sebaris (terutamanya nilai pembolehubah tempatan fungsi luaran) adalah nilai semasa larian ini. Selagi objek fungsi tertanam masih wujud, penutupannya masih wujud (nilai pembolehubah dalam penutupan tidak akan berubah), sekali gus mencapai tujuan menyimpan maklumat tentang proses berjalan fungsi. Pertimbangkan contoh ini:


Salin kod Kod adalah seperti berikut:

var a = "luar";
fungsi f(){
var a = "dalam";
fungsi g(){kembali a;}
Kembalikan g;
}
var hasil = f();
console.log(hasil());//di dalam


Dalam contoh ini, apabila fungsi f() dijalankan, fungsi g() ditakrifkan dan penutupan fungsi g() dibuat Penutupan g() mengandungi rantai objek g_invokeObj-f_invokeObj, sekali gus menjimatkan f() Nilai pembolehubah a semasa pelaksanaan fungsi. Apabila pernyataan console.log() dilaksanakan, kerana objek fungsi g masih wujud, penutupan g() masih wujud apabila menjalankan objek fungsi g yang masih wujud, JavaScript akan menggunakan penutupan g() yang masih wujud dan Dapatkan nilai pembolehubah a ("di dalam") daripadanya.

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn