Rumah  >  Artikel  >  hujung hadapan web  >  Penjelasan terperinci tentang penutupan JavaScript_Pengetahuan asas

Penjelasan terperinci tentang penutupan JavaScript_Pengetahuan asas

WBOY
WBOYasal
2016-05-16 16:16:09949semak imbas

Dalam artikel yang lepas, kami memberikan gambaran pra-tafsiran Sebelum menulis catatan blog ini, kami bercadang untuk menulis beberapa kes klasik Memandangkan kes tersebut agak menyeluruh, kami menulis catatan blog ini secara berperingkat tentang Ia juga lebih mudah untuk mula belajar dan mendalami JavaScript.

Pendahuluan

Seorang rakan sekerja pergi untuk temu duga, dan penemuduga bertanya soalan: Bolehkah anda menulis penutup dan izinkan saya melihat? Jadi rakan sekerja saya dengan cepat menulis kod berikut:

Salin kod Kod adalah seperti berikut:

fungsi fn(){
alert('Hello JavaScript Closure!!!'); // Alamak, teks E tidak bagus, jadi saya terpaksa mencari penterjemah untuk menulis perkataan penutup
}
fn();

Kemudian pewawancara menggelengkan kepalanya dan berkata: "Bagaimana ini boleh dipanggil penutupan?" (Kisah ini adalah rekaan semata-mata, sebarang persamaan adalah kebetulan semata-mata)

Penutupan mungkin merupakan teknologi "mewah dan sukar untuk dipelajari" di mata ramai orang, mungkin pada pandangan ramai orang, ini adalah satu-satunya cara ia boleh dianggap sebagai penutupan:

Contoh 1:

Salin kod Kod adalah seperti berikut:

fungsi fn() {
Kembalikan fungsi () {
makluman('Contoh 1');
}
}
fn()();

Contoh 1 PS: Ini tidak kelihatan sangat maju, nampaknya orang ini tidak begitu baik!

Contoh 2:

Salin kod Kod adalah seperti berikut:

;(fungsi () {
makluman('Contoh 2');
})();

Contoh 2 PS: Yang ini kelihatan lebih maju daripada yang sebelumnya, dan koma bertitik ditambah sebelum kurungan pertama Mengapa menambah koma bertitik Baik, mari tinggalkan soalan ini di sini dan akan membincangkannya kemudian.

Contoh 3:

Salin kod Kod adalah seperti berikut:

~fungsi fn() {
makluman('Contoh 3')
}();

Contoh 3 PS: Ini adalah yang paling maju, saya tidak banyak membaca, jadi jangan berbohong kepada saya!

Saya tidak banyak membaca, jadi saya hanya boleh menulis tiga jenis "penutupan" ini sudah tahu mekanisme bagaimana fungsi itu berjalan. Saya benar-benar tidak mahu menambah skop ini kepada tajuk ini. Tabiat lama, kod dahulu:

Salin kod Kod adalah seperti berikut:

var n = 10;
fungsi fn(){
makluman(n);
var n = 9;
makluman(n);
}
fn();

Ringkasnya, mari lukis gambar (pengarang hanya akan menggunakan perisian lukisan yang disertakan dengan Windows. Jika ada yang lebih baik, sila syorkannya) untuk menganalisisnya:

Analisis 1

Dari gambar kita lihat dua skop, satu adalah skop tetingkap (skop peringkat atas), dan satu lagi adalah skop peribadi yang terbentuk apabila fn dipanggil; maka apa itu skop, skop sebenarnya adalah persekitaran pelaksanaan kod. Sebagai contoh, persekitaran pembelajaran pelajar adalah sekolah, yang setara dengan skopnya Jika pelajar ini sangat nakal dan sering pergi ke kafe Internet untuk bermain permainan pada waktu malam, ia bersamaan dengan membentuk persekitaran peribadi, dan skop ini adalah. Kafe internet. Baiklah! Berangan ini kelihatan sangat sial seperti melancap itu sendiri sehingga saya tidak dapat menahan nafas: "Jika anda tidak bekerja keras semasa anda muda, anda akan ditendang apabila anda dewasa." Berbalik kepada topik, sebenarnya definisi fungsi fn adalah untuk menunjuk kepada penerangan sekeping kod (kotak merah dalam gambar Apabila fn dipanggil (kotak hijau dalam gambar), skop akan terbentuk. Sudah tentu, dalam skop ini Kod ini juga akan ditafsirkan sebelum pelaksanaan. Saya tidak akan memberitahu anda bahawa skop ini akan dimusnahkan selepas ia dilaksanakan semula juga akan membentuk skop baharu, dan kemudiannya sebelum ini pelaksanaan, dan kemudian kod itu akan dimusnahkan selepas pelaksanaan akhir.

Memahami penutupan

Kita tahu bahawa apabila fungsi dipanggil, ia akan membentuk skop peribadi (persekitaran pelaksanaan), dan skop peribadi ini adalah penutupan. Mengimbas kembali, adakah penutupan masih legenda "tinggi dan sukar untuk dikuasai"? Mari kita lihat kembali kisah temu bual pertama dan tiga contoh yang saya tulis itu sebenarnya penutupan.

Senario aplikasi

Sekarang terdapat keperluan sedemikian: terdapat teg ul dalam halaman HTML, dan terdapat 5 teg li di bawah ul. Ia diperlukan untuk mengklik pada mana-mana li, dan indeks (indeks bermula dari 0) kedudukan li yang diklik akan muncul, dan struktur HTML Seperti berikut:

Salin kod Kod adalah seperti berikut:


  • Senarai 1

  • Senarai 2

  • Senarai 3

  • Senarai 4

  • Senarai 5



Oleh kerana bijak, saya dengan pantas menulis kod berikut:

Salin kod Kod adalah seperti berikut:

var lis = document.getElementById('ul').getElementsByTagName('li');
untuk (var i = 0, len = lis.length; i < len; i ) {
lis[i].onclick = fungsi () {
makluman(i);
};
}

Ujian akhir untuk melihat sama ada keperluan ini direalisasikan dengan sempurna:

Saya mendapati bahawa tidak kira berapa kali saya mengklik, keputusan ini akhirnya akan muncul, dan hasil yang diinginkan ialah: klik pada senarai 1 untuk muncul 0, klik pada senarai 2 untuk muncul 1, klik pada senarai 3 hingga timbul 2... Saya hanya mahu menggunakan gambar ini pada masa ini Untuk menggambarkan mood semasa saya:

(Bagaimana rupa apabila prototaip gagal berjalan seperti yang direka semasa demonstrasi)

Bagaimana ini boleh dilakukan Mengapa 5 sentiasa muncul? Secara teorinya betul! Mari lukis gambar untuk menganalisisnya:

Sebenarnya onclick yang kami berikan kepada setiap li sebenarnya adalah rentetan penerangan yang disimpan bagi sesuatu fungsi. Kandungan rentetan ini ialah kandungan dalam kotak merah dalam gambar di atas mempunyai gambar dengan kebenaran:

Masukkan: lis[4].onklik dalam konsol Chrome, nilainya ialah perihalan fungsi. Apabila kita mengklik pada senarai kelima, ia sebenarnya bersamaan dengan lis[4].onclick() Penerangan fungsi ini dipanggil skop juga dipratafsirkan terlebih dahulu, dan kemudian kod dilaksanakan Pada masa ini, i tidak ada dalam skop peribadi semasa, dan kemudian saya ditemui dalam skop tetingkap, jadi 5 muncul setiap kali anda. klik.

Jelas sekali kod di atas tidak dapat memenuhi keperluan ini. Adalah salah untuk kita menulis kod seperti itu. Sebenarnya, sebabnya ialah setiap kali anda klik, anda membaca i di bawah tetingkap Pada masa ini, nilai i sudah 5, jadi anda mempunyai kod berikut:

Kaedah 1:

Salin kod Kod adalah seperti berikut:

var lis = document.getElementById('ul').getElementsByTagName('li');
fungsi fn(i) {
Kembalikan fungsi () {
makluman(i);
}
}
untuk (var i = 0, len = lis.length; i < len; i ) {
lis[i].onclick = fn(i);
}

Kaedah 2:

Salin kod Kod adalah seperti berikut:

var lis = document.getElementById('ul').getElementsByTagName('li');

untuk (var i = 0, len = lis.length; i < len; i ) {
;(fungsi (i) {
lis[i].onclick = fungsi () {
makluman(i);
        };
})(i);
}

Kaedah 3:

Salin kod Kod adalah seperti berikut:

var lis = document.getElementById('ul').getElementsByTagName('li');

untuk (var i = 0, len = lis.length; i < len; i ) {
lis[i].onclick = fungsi fn(i) {
         mengembalikan fungsi () {
makluman(i);
}
}(i);
}

Ich habe drei Methoden in einem Atemzug geschrieben, nämlich die Variable i in einer privaten Variablen zu speichern. Hier werde ich natürlich nur über die zweite Methode sprechen werde den Rest verstehen. Wie üblich zeichnen wir Bilder zur schrittweisen Analyse:

Ich habe die gesamte Codeausführung im Detail beschrieben. Es ist zu beachten, dass das Onclick-Attribut jedes Li den Bereich (function(i){…})(i) belegen muss zerstört werden, da es von einem externen LI belegt ist (dieses LI befindet sich im Fensterbereich), sodass dieser Bereich nicht zerstört wird. Wenn auf ein beliebiges li geklickt wird, wird function(){ warning(i); } ausgeführt und ein Bereich erstellt. Dieser Bereich hat kein i und geht zu (function(){ ... })(. i) Finden Sie i und schließlich den Wert dieses formalen Parameters i, der während der for-Schleife übergeben wird, um Werte zu speichern, was das Problem perfekt löst.

PS: Ich habe gerade erwähnt, warum vor (function(i){ … })(i) ein Semikolon eingefügt wird. Der Grund besteht darin, zu verhindern, dass die vorherige Anweisung vergisst, ein Semikolon hinzuzufügen, was zu JavaScript-Fehlern führt Parsen. Das ist alles. Eines der oben genannten Anwendungsszenarien ist natürlich das Implementierungsprinzip von Tabs. Es kann auch andere Implementierungsmethoden geben, z. B. benutzerdefinierte Attributmethoden und die Suche nach Indizes über DOM-Knotenbeziehungen. Der Hauptzweck der Verwendung dieser Methode besteht darin, das Verständnis von Abschlüssen zu vertiefen .

Zusammenfassung

Schließungen sind nicht die legendären, die schwer zu beherrschen sind. Wenn eine Funktion aufgerufen wird, wird ein neuer privater Bereich gebildet Dieser Bereich wird nicht zerstört. Lu Zhu hat sehr wenig gelesen, daher möchte ich meine Blogger-Kollegen bitten, mich zu korrigieren, wenn ich falsch liege. Ich möchte mich auch bei allen für ihre Unterstützung der Artikel von Lu Zhu bedanken.

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