Saya berusaha sekuat tenaga untuk membungkus kepala saya di sekitar penutupan JavaScript.
Saya mendapatkan bahwa dengan mengembalikan fungsi bagian dalam, itu akan memiliki akses ke variabel apa pun yang ditentukan dalam induk langsungnya.
Di mana ini berguna bagi saya? Mungkin aku belum cukup memahaminya. Sebagian besar contoh yang saya lihat online tidak memberikan kode dunia nyata, hanya contoh samar.
Bisakah seseorang menunjukkan kepada saya penggunaan penutupan di dunia nyata?
Apakah ini, misalnya?
var warnUser = function (msg) {
var calledCount = 0;
return function() {
calledCount++;
alert(msg + '\nYou have been warned ' + calledCount + ' times.');
};
};
var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();
Jawaban:
Saya telah menggunakan penutupan untuk melakukan hal-hal seperti:
Seperti yang Anda lihat di sana,
a
sekarang adalah objek, dengan metodepublicfunction
(a.publicfunction()
) yang memanggilprivatefunction
, yang hanya ada di dalam penutupan. Anda TIDAK bisa meneleponprivatefunction
langsung (yaitua.privatefunction()
), adilpublicfunction()
.Ini contoh minimal tapi mungkin Anda bisa melihat kegunaannya? Kami menggunakan ini untuk menegakkan metode publik / pribadi.
sumber
Misalkan, Anda ingin menghitung berapa kali pengguna mengklik tombol pada halaman web.
Untuk ini, Anda memicu fungsi saat
onclick
tombol untuk memperbarui jumlah variabelSekarang mungkin ada banyak pendekatan seperti:
1) Anda bisa menggunakan variabel global , dan fungsi untuk menambah penghitung :
Namun, jebakannya adalah bahwa skrip apa pun pada laman dapat mengubah penghitung, tanpa menelepon
updateClickCount()
.2) Sekarang, Anda mungkin berpikir untuk mendeklarasikan variabel di dalam fungsi:
Tapi hey! Setiap
updateClickCount()
fungsi waktu dipanggil, penghitung diatur ke 1 lagi.3) Memikirkan fungsi Nested ?
Fungsi bersarang memiliki akses ke ruang lingkup "di atas" mereka.
Dalam contoh ini, fungsi dalam
updateClickCount()
memiliki akses ke variabel counter di fungsi indukcountWrapper()
Ini bisa memecahkan dilema kontra, jika Anda dapat mencapai
updateClickCount()
fungsi dari luar dan Anda juga perlu menemukan cara untuk mengeksekusicounter = 0
hanya sekali tidak setiap kali.4) Penutupan untuk penyelamatan! (fungsi memohon sendiri) :
Fungsi memohon sendiri hanya berjalan sekali. Ini mengatur
counter
ke nol (0), dan mengembalikan ekspresi fungsi.Cara ini
updateClickCount
menjadi fungsi. Bagian "luar biasa" adalah dapat mengakses konter dalam lingkup induk.Ini disebut penutupan JavaScript . Itu memungkinkan suatu fungsi memiliki variabel " pribadi ".
Ini
counter
dilindungi oleh ruang lingkup fungsi anonim, dan hanya dapat diubah menggunakan fungsi add!Contoh yang lebih hidup tentang Penutupan:
Referensi: https://www.w3schools.com/js/js_function_closures.asp
sumber
Contoh yang Anda berikan sangat bagus. Penutupan adalah mekanisme abstraksi yang memungkinkan Anda untuk memisahkan masalah dengan sangat bersih. Contoh Anda adalah kasus pemisahan instrumentasi (penghitungan panggilan) dari semantik (API pelaporan kesalahan). Kegunaan lain termasuk:
Melewati perilaku parameterisasi ke dalam algoritma (pemrograman klasik tingkat tinggi):
Mensimulasikan pemrograman berorientasi objek:
Menerapkan kontrol aliran yang eksotis, seperti penanganan Acara jQuery dan API AJAX.
sumber
int
?) Terakhir saya periksa, JavaScript adalah bahasa yang diketik bebek. Mungkin Anda memikirkan Jawa?Saya tahu saya sangat telat dalam menjawab pertanyaan ini, tetapi mungkin bisa membantu siapa saja yang mencari jawabannya di 2018.
Penutupan Javascript dapat digunakan untuk mengimplementasikan fungsi throttle dan debounce di aplikasi Anda.
Pelambatan :
Throttling memberi batasan sebagai jumlah kali maksimum suatu fungsi dapat dipanggil dari waktu ke waktu. Seperti pada "jalankan fungsi ini paling banyak sekali setiap 100 milidetik."
Kode:
Debouncing :
Debouncing memberi batasan pada fungsi yang tidak dapat dipanggil lagi sampai sejumlah waktu telah berlalu tanpa dipanggil. Seperti dalam "jalankan fungsi ini hanya jika 100 milidetik telah berlalu tanpa dipanggil."
Kode:
Seperti yang Anda lihat, penutupan membantu dalam mengimplementasikan dua fitur cantik yang harus dimiliki setiap aplikasi web untuk menyediakan fungsionalitas pengalaman UI yang lancar.
Saya harap ini akan membantu seseorang.
sumber
Ya, itu adalah contoh bagus dari penutupan yang bermanfaat. Panggilan ke warnUser membuat
calledCount
variabel dalam cakupannya dan mengembalikan fungsi anonim yang disimpan dalamwarnForTamper
variabel. Karena masih ada penutupan menggunakan variabel dipanggilCount, itu tidak dihapus pada saat keluar fungsi, sehingga setiap panggilan kewarnForTamper()
akan meningkatkan variabel cakupan dan mengingatkan nilai.Masalah paling umum yang saya lihat di StackOverflow adalah di mana seseorang ingin "menunda" penggunaan variabel yang meningkat pada setiap loop, tetapi karena variabel tersebut dicakup maka setiap referensi ke variabel akan setelah loop berakhir, menghasilkan status akhir variabel:
Ini akan menghasilkan setiap peringatan yang menunjukkan nilai yang sama
i
, nilai yang dinaikkan menjadi ketika loop berakhir. Solusinya adalah membuat penutupan baru, ruang lingkup terpisah untuk variabel. Ini dapat dilakukan dengan menggunakan fungsi anonim yang dieksekusi langsung, yang menerima variabel dan menyimpan statusnya sebagai argumen:sumber
Dalam bahasa JavaScript (atau ECMAScript), khususnya, penutupan berguna untuk menyembunyikan implementasi fungsi sambil tetap mengungkapkan antarmuka.
Sebagai contoh, bayangkan Anda sedang menulis kelas metode utilitas tanggal dan Anda ingin memungkinkan pengguna untuk mencari nama hari kerja dengan indeks tetapi Anda tidak ingin mereka dapat memodifikasi array nama yang Anda gunakan di bawah tenda.
Perhatikan bahwa
days
array hanya dapat disimpan sebagai propertidateUtil
objek tetapi kemudian akan terlihat oleh pengguna skrip dan mereka bahkan dapat mengubahnya jika mereka mau, tanpa perlu kode sumber Anda. Namun, karena ini dilingkupi oleh fungsi anonim yang mengembalikan fungsi pencarian tanggal itu hanya dapat diakses oleh fungsi pencarian sehingga sekarang rusak-bukti.sumber
Ada bagian tentang Penutupan Praktis di Jaringan Pengembang Mozilla .
sumber
return function ()...
kode masih berfungsi dengan baik. Penutupan itu tidak perluPenggunaan lain yang umum untuk penutupan adalah untuk mengikat
this
suatu metode ke objek tertentu, yang memungkinkannya dipanggil di tempat lain (seperti event handler).Setiap kali acara mousemove kebakaran,
watcher.follow(evt)
disebut.Penutupan juga merupakan bagian penting dari fungsi tingkat tinggi, memungkinkan pola yang sangat umum menulis ulang beberapa fungsi yang sama sebagai fungsi urutan lebih tinggi tunggal dengan parameterisasi bagian yang berbeda. Sebagai contoh abstrak,
menjadi
di mana A dan B bukan unit sintaksis tetapi string kode sumber (bukan string literal).
Lihat " Merampingkan javascript saya dengan suatu fungsi " untuk contoh konkret.
sumber
Di sini, saya punya salam yang ingin saya katakan beberapa kali. Jika saya membuat penutupan, saya cukup memanggil fungsi itu untuk merekam salam. Jika saya tidak membuat penutupan, saya harus memberikan nama saya setiap saat.
Tanpa penutupan ( https://jsfiddle.net/lukeschlangen/pw61qrow/3/ ):
Dengan penutup ( https://jsfiddle.net/lukeschlangen/Lb5cfve9/3/ ):
sumber
Jika Anda nyaman dengan konsep instantiating kelas dalam arti berorientasi objek (yaitu untuk membuat objek kelas itu) maka Anda sudah dekat dengan pemahaman penutupan.
Pikirkan seperti ini: ketika Anda instantiate dua objek Person Anda tahu bahwa variabel anggota kelas "Nama" tidak dibagi antara instance; setiap objek memiliki 'salinan' sendiri. Demikian pula, ketika Anda membuat penutupan, variabel bebas ('dipanggilCount' dalam contoh Anda di atas) terikat ke 'instance' dari fungsi.
Saya pikir lompatan konseptual Anda sedikit terhambat oleh kenyataan bahwa setiap fungsi / penutupan dikembalikan oleh fungsi warnUser (selain: itu adalah fungsi tingkat tinggi ) penutupan mengikat 'disebutCount' dengan nilai awal yang sama (0), sedangkan sering ketika membuat penutupan lebih berguna untuk melewatkan inisialisasi yang berbeda ke dalam fungsi orde tinggi, seperti memberikan nilai yang berbeda ke konstruktor suatu kelas.
Jadi, anggaplah ketika 'dipanggilCount' mencapai nilai tertentu yang Anda ingin mengakhiri sesi pengguna; Anda mungkin menginginkan nilai yang berbeda untuk itu tergantung pada apakah permintaan datang dari jaringan lokal atau internet buruk yang besar (ya, itu adalah contoh yang dibuat-buat). Untuk mencapai ini, Anda bisa meneruskan nilai awal yang berbeda untuk dipanggilCount ke warnUser (yaitu -3, atau 0?).
Bagian dari masalah dengan literatur adalah nomenklatur yang digunakan untuk menggambarkan mereka ("ruang lingkup leksikal", "variabel bebas"). Jangan biarkan itu membodohi Anda, penutupan lebih sederhana daripada yang akan muncul ... prima facie ;-)
sumber
Di sini saya punya satu contoh sederhana konsep penutupan yang dapat kita gunakan di situs E-commerce kami atau banyak lainnya juga. Saya menambahkan tautan jsfiddle saya dengan contoh. itu berisi daftar produk kecil 3 item dan satu gerobak gerobak.
Jsfiddle
sumber
Penggunaan Penutupan:
Penutupan adalah salah satu fitur paling kuat dari JavaScript. JavaScript memungkinkan untuk fungsi bersarang dan memberikan fungsi penuh akses penuh ke fungsi dalam semua variabel dan fungsi yang didefinisikan di dalam fungsi luar (dan semua variabel dan fungsi lain yang memiliki fungsi akses luar). Namun, fungsi luar tidak memiliki akses ke variabel dan fungsi yang didefinisikan di dalam fungsi dalam. Ini memberikan semacam keamanan untuk variabel fungsi dalam. Juga, karena fungsi dalam memiliki akses ke ruang lingkup fungsi luar, variabel dan fungsi yang didefinisikan dalam fungsi luar akan hidup lebih lama daripada fungsi luar itu sendiri, jika fungsi dalam berhasil bertahan hidup di luar kehidupan fungsi luar.
Contoh:
Dalam kode di atas, variabel nama dari fungsi luar dapat diakses oleh fungsi dalam, dan tidak ada cara lain untuk mengakses variabel dalam kecuali melalui fungsi dalam. Variabel-variabel dalam dari fungsi dalam bertindak sebagai simpanan yang aman untuk fungsi-fungsi dalam. Mereka menyimpan "persisten", namun aman, data untuk fungsi internal untuk bekerja dengannya. Fungsi-fungsinya bahkan tidak harus ditugaskan ke variabel, atau memiliki nama. baca di sini untuk detailnya
sumber
Saya suka contoh fungsi pabrik Mozilla .
sumber
Pola modul JavaScript menggunakan penutupan. Pola yang bagus memungkinkan Anda untuk memiliki sesuatu yang sama "publik" dan "pribadi" vars.
sumber
Saya menulis sebuah artikel beberapa waktu lalu tentang bagaimana penutupan dapat digunakan untuk menyederhanakan kode penanganan kejadian. Ini membandingkan penanganan acara ASP.NET dengan jQuery sisi klien.
http://www.hackification.com/2009/02/20/closures-simplify-event-handling-code/
sumber
Utas ini sangat membantu saya dalam mendapatkan pemahaman yang lebih baik tentang bagaimana penutupan bekerja. Sejak itu saya telah melakukan beberapa eksperimen sendiri dan menghasilkan kode yang cukup sederhana ini yang dapat membantu beberapa orang melihat bagaimana penutupan dapat digunakan dengan cara yang praktis dan bagaimana menggunakan penutupan pada tingkat yang berbeda untuk mempertahankan variabel yang mirip dengan statis dan / atau variabel global tanpa risiko mereka ditimpa atau dikacaukan dengan variabel global. Apa yang dilakukan adalah melacak klik tombol, baik di tingkat lokal untuk setiap tombol individu dan tingkat global, menghitung setiap klik tombol, berkontribusi terhadap satu angka. Catatan Saya belum pernah menggunakan variabel global untuk melakukan ini, yang merupakan inti dari latihan - memiliki penangan yang dapat diterapkan pada tombol apa pun yang juga berkontribusi pada sesuatu secara global.
Tolong para ahli, beri tahu saya jika saya melakukan praktik buruk di sini! Saya sendiri masih mempelajari hal ini.
sumber
Referensi: Penggunaan praktis penutupan
Dalam praktiknya, penutupan dapat membuat desain yang elegan, memungkinkan penyesuaian berbagai perhitungan, panggilan yang ditangguhkan, panggilan balik, membuat lingkup yang dienkapsulasi dll.
Contoh metode pengurutan array yang menerima sebagai argumen fungsi pengurutan kondisi:
Memetakan fungsional sebagai metode peta array yang memetakan array baru dengan kondisi argumen fungsional:
Seringkali lebih mudah untuk mengimplementasikan fungsi pencarian dengan menggunakan argumen fungsional yang mendefinisikan kondisi pencarian yang hampir tidak terbatas:
Selain itu, kami dapat mencatat penerapan fungsi sebagai, misalnya, metode forEach yang menerapkan fungsi ke array elemen:
Fungsi diterapkan pada argumen (ke daftar argumen - berlaku, dan argumen diposisikan - dalam panggilan):
Panggilan yang ditangguhkan:
Fungsi panggilan balik:
Pembuatan lingkup enkapsulasi untuk tujuan menyembunyikan objek tambahan:
sumber
Biola
sumber
Penutupan adalah cara yang berguna untuk membuat generator, urutan yang bertambah saat diminta:
Perbedaannya diringkas sebagai berikut:
Referensi
sumber
Dalam sampel yang diberikan nilai 'counter' variabel terlampir dilindungi dan hanya dapat diubah dengan menggunakan fungsi yang diberikan (increment, decrement). karena itu dalam penutupan,
sumber
Menjelaskan penggunaan praktis untuk Penutupan dalam JavaScript ---
Saat kami membuat fungsi di dalam fungsi lain, kami membuat penutupan. Penutupan sangat kuat karena mereka mampu membaca dan memanipulasi data fungsi luarnya. Setiap kali fungsi dipanggil, ruang lingkup baru dibuat untuk panggilan itu. Variabel lokal yang dideklarasikan di dalam fungsi milik lingkup itu dan mereka hanya dapat diakses dari fungsi itu. Ketika fungsi telah menyelesaikan eksekusi, ruang lingkup biasanya dihancurkan.
Contoh sederhana dari fungsi tersebut adalah ini:
Dalam contoh di atas, fungsi buildName () mendeklarasikan salam variabel lokal dan mengembalikannya. Setiap panggilan fungsi menciptakan ruang lingkup baru dengan variabel lokal baru. Setelah fungsi selesai dieksekusi, kami tidak memiliki cara untuk merujuk ke lingkup itu lagi, jadi itu mengumpulkan sampah.
Tapi bagaimana kalau kita memiliki tautan ke ruang lingkup itu?
Mari kita lihat fungsi selanjutnya:
Fungsi sayName () dari contoh ini adalah penutupan. Fungsi sayName () memiliki cakupan lokalnya sendiri (dengan variabel sambutan) dan juga memiliki akses ke lingkup fungsi luar (melampirkan). Dalam hal ini, salam variabel dari buildName ().
Setelah eksekusi buildName dilakukan, ruang lingkup tidak dihancurkan dalam kasus ini. Fungsi sayMyName () masih memiliki akses ke sana, jadi itu tidak akan menjadi sampah yang dikumpulkan. Namun, tidak ada cara lain untuk mengakses data dari lingkup luar kecuali penutupan. Penutupan berfungsi sebagai pintu gerbang antara konteks global dan lingkup luar.
sumber
Saya mencoba mempelajari clousures dan saya pikir contoh yang saya buat adalah use case yang praktis. Anda dapat menjalankan cuplikan dan melihat hasilnya di konsol. kami memiliki dua pengguna terpisah yang memiliki data terpisah. Masing-masing dari mereka dapat melihat keadaan aktual dan memperbaruinya.
sumber