Saya mengajukan pertanyaan tentang Kari dan penutupan disebutkan. Apa itu penutupan? Bagaimana hubungannya dengan kari?
432
Saya mengajukan pertanyaan tentang Kari dan penutupan disebutkan. Apa itu penutupan? Bagaimana hubungannya dengan kari?
Jawaban:
Lingkup variabel
Saat Anda mendeklarasikan variabel lokal, variabel itu memiliki cakupan. Secara umum, variabel lokal hanya ada di dalam blok atau fungsi tempat Anda mendeklarasikannya.
Jika saya mencoba mengakses variabel lokal, sebagian besar bahasa akan mencarinya dalam cakupan saat ini, kemudian naik melalui cakupan induk hingga mencapai lingkup root.
Ketika suatu blok atau fungsi selesai, variabel lokalnya tidak lagi diperlukan dan biasanya dihembuskan dari memori.
Beginilah biasanya kita mengharapkan sesuatu bekerja.
Penutupan adalah ruang lingkup variabel lokal yang persisten
Penutupan adalah ruang lingkup persisten yang berpegang pada variabel lokal bahkan setelah eksekusi kode telah pindah dari blok itu. Bahasa yang mendukung penutupan (seperti JavaScript, Swift, dan Ruby) akan memungkinkan Anda untuk menyimpan referensi ke ruang lingkup (termasuk cakupan induknya), bahkan setelah blok di mana variabel-variabel tersebut dinyatakan telah selesai dieksekusi, asalkan Anda menyimpan referensi ke blok itu atau berfungsi di suatu tempat.
Objek lingkup dan semua variabel lokalnya terikat dengan fungsi dan akan bertahan selama fungsi itu tetap ada.
Ini memberi kita portabilitas fungsi. Kita dapat mengharapkan variabel apa pun yang berada dalam ruang lingkup ketika fungsi pertama kali didefinisikan masih dalam ruang lingkup ketika kita memanggil fungsi, bahkan jika kita memanggil fungsi dalam konteks yang sama sekali berbeda.
Sebagai contoh
Berikut adalah contoh yang sangat sederhana dalam JavaScript yang menggambarkan intinya:
Di sini saya telah mendefinisikan suatu fungsi di dalam suatu fungsi. Fungsi dalam memperoleh akses ke semua variabel lokal fungsi luar, termasuk
a
. Variabela
dalam ruang lingkup untuk fungsi dalam.Biasanya ketika suatu fungsi keluar, semua variabel lokalnya terpesona. Namun, jika kita mengembalikan fungsi bagian dalam dan menetapkannya ke variabel
fnc
sehingga tetap ada setelahouter
keluar, semua variabel yang berada dalam ruang lingkup saatinner
didefinisikan juga tetap ada . Variabela
telah ditutup - itu dalam penutupan.Perhatikan bahwa variabel
a
tersebut benar-benar pribadi untukfnc
. Ini adalah cara membuat variabel pribadi dalam bahasa pemrograman fungsional seperti JavaScript.Seperti yang mungkin bisa Anda tebak, ketika saya menyebutnya
fnc()
mencetak nilaia
, yaitu "1".Dalam bahasa tanpa penutupan, variabel
a
akan menjadi sampah yang dikumpulkan dan dibuang ketika fungsiouter
keluar. Memanggil fnc akan membuat kesalahan karenaa
tidak ada lagi.Dalam JavaScript, variabel
a
tetap ada karena ruang lingkup variabel dibuat ketika fungsi pertama kali dideklarasikan dan bertahan selama fungsi terus ada.a
termasuk dalam ruang lingkupouter
. Ruang lingkupinner
memiliki pointer orangtua ke lingkupouter
.fnc
adalah variabel yang menunjuk keinner
.a
tetap ada selama masihfnc
ada.a
berada dalam penutupan.sumber
Saya akan memberikan contoh (dalam JavaScript):
Apa fungsi ini, makeCounter, lakukan adalah mengembalikan fungsi, yang kami sebut x, yang akan dihitung satu setiap kali dipanggil. Karena kami tidak memberikan parameter apa pun kepada x, entah bagaimana ia harus mengingat hitungan. Ia tahu di mana menemukannya berdasarkan apa yang disebut pelingkupan leksikal - ia harus melihat ke tempat di mana ia didefinisikan untuk menemukan nilai. Nilai "tersembunyi" ini adalah apa yang disebut penutupan.
Ini adalah contoh kari saya lagi:
Apa yang dapat Anda lihat adalah bahwa ketika Anda memanggil add dengan parameter a (yang adalah 3), nilai itu terkandung dalam penutupan fungsi yang dikembalikan yang kami definisikan sebagai add3. Dengan begitu, ketika kita memanggil add3 ia tahu di mana menemukan nilai untuk melakukan penambahan.
sumber
Jawaban Kyle cukup bagus. Saya pikir satu-satunya klarifikasi tambahan adalah bahwa penutupan pada dasarnya adalah snapshot dari tumpukan pada titik fungsi lambda dibuat. Kemudian ketika fungsi dijalankan kembali tumpukan dikembalikan ke keadaan itu sebelum menjalankan fungsi. Jadi seperti Kyle menyebutkan, bahwa nilai tersembunyi (
count
) tersedia ketika fungsi lambda dijalankan.sumber
Pertama-tama, bertentangan dengan apa yang dikatakan sebagian besar orang di sini, penutupan bukanlah suatu fungsi ! Jadi apa yang itu?
Ini adalah seperangkat simbol yang didefinisikan dalam "konteks sekitarnya" fungsi (dikenal sebagai lingkungannya ) yang membuatnya menjadi ekspresi TERTUTUP (yaitu, ekspresi di mana setiap simbol didefinisikan dan memiliki nilai, sehingga dapat dievaluasi).
Misalnya, ketika Anda memiliki fungsi JavaScript:
itu adalah ekspresi tertutup karena semua simbol yang ada di dalamnya didefinisikan di dalamnya (artinya jelas), sehingga Anda dapat mengevaluasinya. Dengan kata lain, itu mandiri .
Tetapi jika Anda memiliki fungsi seperti ini:
itu adalah ekspresi terbuka karena ada simbol di dalamnya yang belum didefinisikan di dalamnya. Yaitu
y
,. Ketika melihat fungsi ini, kita tidak bisa mengatakan apay
itu dan apa artinya, kita tidak tahu nilainya, jadi kita tidak bisa mengevaluasi ungkapan ini. Yaitu kita tidak dapat memanggil fungsi ini sampai kita tahu apay
yang dimaksudkan di dalamnya. Iniy
disebut variabel bebas .Ini
y
memohon definisi, tetapi definisi ini bukan bagian dari fungsi - itu didefinisikan di tempat lain, dalam "konteks sekitarnya" (juga dikenal sebagai lingkungan ). Setidaknya itulah yang kami harapkan: PSebagai contoh, ini dapat didefinisikan secara global:
Atau bisa didefinisikan dalam fungsi yang membungkusnya:
Bagian dari lingkungan yang memberikan variabel bebas dalam ekspresi artinya, adalah penutup . Ini disebut cara ini, karena mengubah ekspresi terbuka menjadi ekspresi tertutup , dengan menyediakan definisi yang hilang ini untuk semua variabel bebasnya , sehingga kami dapat mengevaluasinya.
Dalam contoh di atas, fungsi bagian dalam (yang kami tidak memberikan nama karena kami tidak membutuhkannya) adalah ekspresi terbuka karena variabel
y
di dalamnya bebas - definisinya berada di luar fungsi, dalam fungsi yang membungkusnya . The lingkungan untuk itu fungsi anonim adalah himpunan variabel:Sekarang, penutupan adalah bagian dari lingkungan ini yang menutup fungsi bagian dalam dengan menyediakan definisi untuk semua variabel bebasnya . Dalam kasus kami, satu-satunya variabel bebas dalam fungsi dalam adalah
y
, jadi penutupan fungsi itu adalah bagian dari lingkungannya:Dua simbol lain yang didefinisikan dalam lingkungan bukan bagian dari penutupan fungsi itu, karena itu tidak mengharuskan mereka untuk menjalankan. Mereka tidak perlu menutupnya .
Lebih lanjut tentang teori di balik itu di sini: https://stackoverflow.com/a/36878651/434562
Perlu dicatat bahwa dalam contoh di atas, fungsi wrapper mengembalikan fungsi bagian dalamnya sebagai nilai. Saat kita memanggil fungsi ini dapat menjadi jauh dalam waktu dari saat fungsi telah didefinisikan (atau dibuat). Secara khusus, fungsi pembungkusnya tidak lagi berjalan, dan parameternya yang sudah ada di tumpukan panggilan sudah tidak ada lagi: P Ini membuat masalah, karena fungsi bagian dalam
y
harus ada ketika dipanggil! Dengan kata lain, itu membutuhkan variabel dari penutupannya untuk entah bagaimana hidup lebih lama dari fungsi pembungkus dan berada di sana ketika dibutuhkan. Oleh karena itu, fungsi bagian dalam harus membuat snapshot dari variabel-variabel ini yang membuat penutupannya dan menyimpannya di tempat yang aman untuk digunakan nanti. (Di suatu tempat di luar tumpukan panggilan.)Dan inilah mengapa orang sering mengacaukan istilah closure sebagai jenis fungsi khusus yang dapat melakukan snapshot dari variabel eksternal yang mereka gunakan, atau struktur data yang digunakan untuk menyimpan variabel-variabel ini untuk nanti. Tapi saya harap Anda mengerti sekarang bahwa itu bukan penutupan itu sendiri - itu hanya cara untuk menerapkan penutupan dalam bahasa pemrograman, atau mekanisme bahasa yang memungkinkan variabel dari penutupan fungsi berada di sana saat dibutuhkan. Ada banyak kesalahpahaman di sekitar penutupan yang (tidak perlu) membuat subjek ini jauh lebih membingungkan dan rumit.
sumber
Penutupan adalah fungsi yang bisa merujuk keadaan di fungsi lain. Misalnya, dalam Python, ini menggunakan penutupan "bagian dalam":
sumber
Untuk membantu memfasilitasi pemahaman tentang penutupan, mungkin berguna untuk memeriksa bagaimana mereka diimplementasikan dalam bahasa prosedural. Penjelasan ini akan mengikuti implementasi penutupan yang sederhana dalam Skema.
Untuk memulai, saya harus memperkenalkan konsep namespace. Saat Anda memasukkan perintah ke dalam juru bahasa Skema, itu harus mengevaluasi berbagai simbol dalam ekspresi dan mendapatkan nilainya. Contoh:
Ekspresi define menyimpan nilai 3 di tempat untuk x dan nilai 4 di tempat untuk y. Kemudian ketika kita memanggil (+ xy), interpreter mencari nilai-nilai di namespace dan dapat melakukan operasi dan mengembalikan 7.
Namun, dalam Skema ada ekspresi yang memungkinkan Anda untuk sementara menimpa nilai simbol. Ini sebuah contoh:
Apa yang dilakukan kata kunci let adalah memperkenalkan namespace baru dengan x sebagai nilai 5. Anda akan melihat bahwa itu masih dapat melihat bahwa y adalah 4, sehingga jumlah yang dikembalikan menjadi 9. Anda juga dapat melihat bahwa setelah ekspresi telah berakhir x kembali menjadi 3. Dalam pengertian ini, x telah ditutup sementara oleh nilai lokal.
Bahasa prosedural dan berorientasi objek memiliki konsep yang sama. Setiap kali Anda mendeklarasikan variabel dalam suatu fungsi yang memiliki nama yang sama dengan variabel global Anda mendapatkan efek yang sama.
Bagaimana kita menerapkan ini? Cara sederhana adalah dengan daftar tertaut - kepala berisi nilai baru dan ekornya berisi namespace lama. Ketika Anda perlu mencari simbol, Anda mulai dari kepala dan turun ke bagian bawah.
Sekarang mari kita lompat ke implementasi fungsi kelas satu untuk saat ini. Lebih atau kurang, suatu fungsi adalah seperangkat instruksi untuk dieksekusi ketika fungsi disebut memuncak pada nilai kembali. Ketika kita membaca suatu fungsi, kita dapat menyimpan instruksi ini di belakang layar dan menjalankannya ketika fungsi tersebut dipanggil.
Kami mendefinisikan x menjadi 3 dan plus-x sebagai parameternya, y, ditambah nilai x. Akhirnya kita memanggil plus-x di lingkungan di mana x telah ditutup oleh x baru, yang ini bernilai 5. Jika kita hanya menyimpan operasi, (+ xy), untuk fungsi plus-x, karena kita berada dalam konteks dari x menjadi 5 hasil yang dikembalikan adalah 9. Inilah yang disebut pelingkupan dinamis.
Namun, Skema, Common Lisp, dan banyak bahasa lain memiliki apa yang disebut pelingkupan leksikal - selain menyimpan operasi (+ xy) kami juga menyimpan namespace pada titik tertentu. Dengan begitu, ketika kita mencari nilai-nilai kita dapat melihat bahwa x, dalam konteks ini, benar-benar 3. Ini adalah penutup.
Singkatnya, kita bisa menggunakan daftar tertaut untuk menyimpan keadaan namespace pada saat definisi fungsi, memungkinkan kita untuk mengakses variabel dari lingkup melampirkan, serta memberikan kita kemampuan untuk secara lokal menutupi variabel tanpa mempengaruhi sisa dari program.
sumber
Why do we want to access variables that are out of scope? when we say let x = 5, we want x to be 5 and not 3. What is happening?
Berikut ini adalah contoh nyata dari dunia mengapa Closures menendang pantat ... Ini langsung dari kode Javascript saya. Biarkan saya ilustrasikan.
Dan inilah cara Anda menggunakannya:
Sekarang bayangkan Anda ingin pemutaran mulai ditunda, seperti misalnya 5 detik kemudian setelah potongan kode ini berjalan. Yah itu mudah dengan
delay
dan itu penutupan:Saat Anda menelepon
delay
dengan5000
ms, cuplikan pertama berjalan, dan menyimpan argumen yang diteruskan di penutupannya. Kemudian 5 detik kemudian, ketikasetTimeout
panggilan balik terjadi, penutupan masih mempertahankan variabel-variabel tersebut, sehingga dapat memanggil fungsi asli dengan parameter asli.Ini adalah jenis kari, atau fungsi dekorasi.
Tanpa penutup, Anda harus mempertahankan status variabel tersebut di luar fungsi, sehingga membuang kode di luar fungsi dengan sesuatu yang secara logis berada di dalamnya. Menggunakan penutupan dapat sangat meningkatkan kualitas dan keterbacaan kode Anda.
sumber
Fungsi yang tidak mengandung variabel bebas disebut fungsi murni.
Fungsi yang mengandung satu atau lebih variabel bebas disebut closure.
src: https://leanpub.com/javascriptallongesix/read#leanpub-auto-if-functions-without-free-variables-are-pure-are-closures-impure
sumber
tl; dr
Penutupan adalah fungsi dan ruang lingkupnya ditetapkan untuk (atau digunakan sebagai) variabel. Dengan demikian, penutupan nama: ruang lingkup dan fungsi tertutup dan digunakan sama seperti entitas lainnya.
Penjelasan gaya Wikipedia yang mendalam
Menurut Wikipedia, penutupan adalah:
Apa artinya? Mari kita melihat beberapa definisi.
Saya akan menjelaskan penutupan dan definisi terkait lainnya dengan menggunakan contoh ini:
Fungsi kelas satu
Pada dasarnya itu berarti kita dapat menggunakan fungsi seperti entitas lainnya . Kita dapat memodifikasinya, meneruskannya sebagai argumen, mengembalikannya dari fungsi atau menetapkannya untuk variabel. Secara teknis, mereka adalah warga negara kelas satu , karenanya namanya: fungsi kelas satu.
Dalam contoh di atas,
startAt
mengembalikan fungsi ( anonim ) yang fungsinya ditugaskan untukclosure1
danclosure2
. Jadi seperti yang Anda lihat JavaScript memperlakukan fungsi sama seperti entitas lainnya (warga negara kelas satu).Mengikat nama
Pengikatan nama adalah tentang mencari tahu data apa yang menjadi referensi variabel (pengidentifikasi) . Lingkup ini sangat penting di sini, karena hal itulah yang akan menentukan bagaimana suatu ikatan diselesaikan.
Dalam contoh di atas:
y
terikat3
.startAt
ruang lingkup,x
terikat ke1
atau5
(tergantung pada penutupan).Di dalam ruang lingkup fungsi anonim,
x
tidak terikat dengan nilai apa pun, jadi itu perlu diselesaikan dalamstartAt
ruang lingkup atas.Pelingkupan leksikal
Seperti yang dikatakan Wikipedia , ruang lingkup:
Ada dua teknik:
Untuk penjelasan lebih lanjut, lihat pertanyaan ini dan lihat di Wikipedia .
Pada contoh di atas, kita dapat melihat bahwa JavaScript dibatasi secara leksikal, karena ketika
x
diselesaikan, pengikatan dicari dalamstartAt
lingkup atas, berdasarkan pada kode sumber (fungsi anonim yang mencari x didefinisikan di dalamstartAt
) dan tidak berdasarkan tumpukan panggilan, cara (ruang lingkup di mana) fungsi dipanggil.Membungkus (menutup)
Dalam contoh kita, ketika kita memanggil
startAt
, itu akan mengembalikan fungsi (kelas satu) yang akan ditugaskanclosure1
danclosure2
dengan demikian penutupan dibuat, karena variabel yang dikirimkan1
dan5
akan disimpan dalamstartAt
ruang lingkup, yang akan ditutup dengan yang dikembalikan fungsi anonim. Ketika kita memanggil fungsi anonim ini melaluiclosure1
danclosure2
dengan argumen yang sama (3
), nilaiy
akan segera ditemukan (karena itu adalah parameter dari fungsi itu), tetapix
tidak terikat dalam ruang lingkup fungsi anonim, sehingga resolusi berlanjut di (fungsi leksikal) lingkup fungsi atas (yang disimpan dalam penutupan) di manax
ditemukan terikat ke salah satu1
atau5
. Sekarang kita tahu segalanya untuk penjumlahan sehingga hasilnya dapat dikembalikan, lalu dicetak.Sekarang Anda harus memahami penutupan dan bagaimana mereka berperilaku, yang merupakan bagian mendasar dari JavaScript.
Kari
Oh, dan Anda juga mempelajari apa itu currying : Anda menggunakan fungsi (penutup) untuk melewati setiap argumen operasi bukannya menggunakan satu fungsi dengan beberapa parameter.
sumber
Penutupan adalah fitur dalam JavaScript di mana fungsi memiliki akses ke variabel lingkupnya sendiri, akses ke variabel fungsi luar dan akses ke variabel global.
Penutupan memiliki akses ke lingkup fungsi luarnya bahkan setelah fungsi luar kembali. Ini berarti penutupan dapat mengingat dan mengakses variabel dan argumen dari fungsi luarnya bahkan setelah fungsi selesai.
Fungsi dalam dapat mengakses variabel yang didefinisikan dalam ruang lingkupnya sendiri, ruang lingkup fungsi luar, dan ruang lingkup global. Dan fungsi luar dapat mengakses variabel yang ditentukan dalam lingkupnya sendiri dan lingkup global.
Contoh Penutupan :
Output akan menjadi 20 yang jumlah variabel fungsi dalamnya sendiri, variabel fungsi luar dan nilai variabel global.
sumber
Dalam situasi normal, variabel terikat oleh aturan pelingkupan: Variabel lokal hanya berfungsi dalam fungsi yang ditentukan. Penutupan adalah cara melanggar aturan ini sementara untuk kenyamanan.
dalam kode di atas,
lambda(|n| a_thing * n}
adalah penutupan karenaa_thing
disebut oleh lambda (pembuat fungsi anonim).Sekarang, jika Anda meletakkan fungsi anonim yang dihasilkan dalam variabel fungsi.
foo akan melanggar aturan pelingkupan normal dan mulai menggunakan 4 secara internal.
mengembalikan 12.
sumber
Singkatnya, pointer fungsi hanyalah sebuah pointer ke lokasi di basis kode program (seperti penghitung program). Sedangkan Closure = Function pointer + Stack frame .
.
sumber
• Penutupan adalah subprogram dan lingkungan referensi tempat definisi itu ditentukan
- Lingkungan referensi diperlukan jika subprogram dapat dipanggil dari sembarang tempat dalam program
- Bahasa dengan cakupan statis yang tidak mengizinkan subprogram bersarang tidak perlu ditutup
- Penutupan hanya diperlukan jika subprogram dapat mengakses variabel dalam cakupan bersarang dan dapat dipanggil dari mana saja
- Untuk mendukung penutupan, implementasi mungkin perlu memberikan batas tidak terbatas pada beberapa variabel (karena subprogram dapat mengakses variabel nonlokal yang biasanya tidak lagi hidup)
Contoh
sumber
Berikut adalah contoh kehidupan nyata yang lain, dan menggunakan bahasa scripting yang populer di permainan - Lua. Saya perlu sedikit mengubah cara fungsi perpustakaan bekerja untuk menghindari masalah dengan stdin tidak tersedia.
Nilai old_dofile menghilang ketika blok kode ini menyelesaikan ruang lingkupnya (karena bersifat lokal), namun nilainya telah ditutup dalam penutupan, sehingga fungsi dofile baru yang didefinisikan ulang DAPAT mengaksesnya, atau lebih tepatnya salinan yang disimpan bersama dengan fungsi sebagai 'upvalue'.
sumber
Dari Lua.org :
sumber
Jika Anda berasal dari dunia Java, Anda dapat membandingkan penutupan dengan fungsi anggota suatu kelas. Lihatlah contoh ini
Fungsi
g
adalah penutupan:g
menutupa
di Jadi.g
Dapat dibandingkan dengan fungsi anggota,a
dapat dibandingkan dengan bidang kelas, dan fungsif
dengan kelas.sumber
Penutupan Setiap kali kita memiliki fungsi yang didefinisikan di dalam fungsi lain, fungsi dalam memiliki akses ke variabel yang dinyatakan dalam fungsi luar. Penutupan paling baik dijelaskan dengan contoh. Dalam Listing 2-18, Anda bisa melihat bahwa fungsi dalam memiliki akses ke variabel (variableInOuterFunction) dari lingkup luar. Variabel dalam fungsi luar telah ditutup oleh (atau terikat) fungsi dalam. Karena itu istilah penutupan. Konsep itu sendiri cukup sederhana dan cukup intuitif.
sumber: http://index-of.es/Varios/Basarat%20Ali%20Syed%20(auth.)-Beginning%20Node.js-Apress%20(2014).pdf
sumber
Silakan lihat kode di bawah ini untuk memahami penutupan lebih dalam:
Di sini apa yang akan menjadi output?
0,1,2,3,4
bukan5,5,5,5,5
karena penutupanJadi bagaimana itu akan menyelesaikannya? Jawabannya di bawah:
Biar saya jelaskan, ketika suatu fungsi dibuat tidak ada yang terjadi sampai ia dipanggil untuk loop dalam kode 1 disebut 5 kali tetapi tidak dipanggil segera jadi ketika dipanggil yaitu setelah 1 detik dan juga ini tidak sinkron jadi sebelum ini untuk loop selesai dan menyimpan nilai 5 di var i dan akhirnya jalankan
setTimeout
fungsi lima kali dan cetak5,5,5,5,5
Di sini cara mengatasi menggunakan IIFE yaitu Ekspresi Fungsi Immediate Invoking
Untuk lebih lanjut, harap pahami konteks eksekusi untuk memahami penutupan.
Ada satu solusi lagi untuk menyelesaikan ini menggunakan let (fitur ES6) tetapi di bawah kap fungsi di atas bekerja
=> Penjelasan lebih lanjut:
Di memori, ketika untuk loop jalankan gambar make seperti di bawah ini:
Loop 1)
Loop 2)
Loop 3)
Loop 4)
Loop 5)
Di sini saya tidak dieksekusi dan kemudian setelah loop lengkap, var saya menyimpan nilai 5 dalam memori tetapi ruang lingkupnya selalu terlihat dalam fungsi anak-anak sehingga ketika fungsi dijalankan dalam
setTimeout
lima kali ia dicetak5,5,5,5,5
jadi untuk mengatasi ini gunakan IIFE seperti yang dijelaskan di atas.
sumber
Currying: Ini memungkinkan Anda untuk mengevaluasi sebagian fungsi dengan hanya mengirimkan sebagian dari argumennya. Pertimbangkan ini:
Penutupan: Penutupan tidak lebih dari mengakses variabel di luar lingkup fungsi. Penting untuk diingat bahwa fungsi di dalam suatu fungsi atau fungsi bersarang bukanlah penutupan. Penutupan selalu digunakan ketika perlu mengakses variabel di luar lingkup fungsi.
sumber
Penutupan sangat mudah. Kita dapat mempertimbangkannya sebagai berikut: Penutupan = fungsi + lingkungan leksikalnya
Pertimbangkan fungsi berikut:
Apa yang akan menjadi penutupan dalam kasus di atas? Function init () dan variabel dalam lingkungan leksikalnya yaitu nama. Penutupan = init () + nama
Pertimbangkan fungsi lain:
Apa yang akan menjadi penutupan di sini? Fungsi dalam dapat mengakses variabel fungsi luar. displayName () dapat mengakses nama variabel yang dinyatakan dalam fungsi induk, init (). Namun, variabel lokal yang sama di displayName () akan digunakan jika ada.
Penutupan 1: fungsi init + (variabel nama + fungsi displayName ()) -> ruang lingkup leksikal
Penutupan 2: fungsi displayName + (variabel nama) -> ruang lingkup leksikal
sumber
Penutupan memberi status pada JavaScript.
Keadaan dalam pemrograman berarti mengingat sesuatu.
Contoh
Dalam kasus di atas, status disimpan dalam variabel "a". Kami mengikuti dengan menambahkan 1 ke "a" beberapa kali. Kita hanya dapat melakukan itu karena kita dapat "mengingat" nilainya. Pemegang status, "a", menyimpan nilai itu dalam memori.
Seringkali, dalam bahasa pemrograman, Anda ingin melacak hal-hal, mengingat informasi dan mengaksesnya di lain waktu.
Ini, dalam bahasa lain , umumnya dicapai melalui penggunaan kelas. Kelas, seperti halnya variabel, melacak kondisinya. Dan contoh-contoh dari kelas itu, pada gilirannya, juga memiliki keadaan di dalamnya. Negara hanya berarti informasi yang dapat Anda simpan dan ambil nanti.
Contoh
Bagaimana kita dapat mengakses "bobot" dari dalam metode "render"? Yah, terima kasih sudah menyatakan. Setiap instance dari class Bread dapat memberikan bobotnya sendiri dengan membacanya dari "state", tempat di memori di mana kita dapat menyimpan informasi itu.
Sekarang, JavaScript adalah bahasa yang sangat unik yang yang secara historis tidak memiliki kelas (sekarang, tetapi di bawah tenda hanya ada fungsi dan variabel) sehingga Closures menyediakan cara bagi JavaScript untuk mengingat sesuatu dan mengaksesnya nanti.
Contoh
Contoh di atas mencapai tujuan "menjaga keadaan" dengan variabel. Ini bagus! Namun, ini memiliki kelemahan bahwa variabel (pemegang "negara") sekarang terbuka. Kita bisa melakukan yang lebih baik. Kita bisa menggunakan Penutupan.
Contoh
Ini fantastis.
Sekarang fungsi "menghitung" kami dapat menghitung. Ia hanya dapat melakukannya karena ia dapat "menahan" keadaan. Keadaan dalam hal ini adalah variabel "n". Variabel ini sekarang ditutup. Tertutup dalam ruang dan waktu. Pada waktunya karena Anda tidak akan pernah dapat memulihkannya, ubah, tetapkan nilai, atau berinteraksi langsung dengannya. Di ruang angkasa karena secara geografis bersarang di dalam fungsi "countGenerator".
Kenapa ini fantastis? Karena tanpa melibatkan alat canggih dan rumit lainnya (misalnya kelas, metode, instance, dll) kita dapat 1. menyembunyikan 2. mengontrol dari kejauhan
Kami menyembunyikan negara, variabel "n", yang membuatnya menjadi variabel pribadi! Kami juga telah membuat API yang dapat mengontrol variabel ini dengan cara yang telah ditentukan sebelumnya. Secara khusus, kita dapat memanggil API seperti "count ()" dan itu menambahkan 1 ke "n" dari "jarak". Dengan cara apa pun, bentuk atau bentuk siapa pun tidak akan dapat mengakses "n" kecuali melalui API.
JavaScript benar-benar luar biasa dalam kesederhanaannya.
Penutupan adalah bagian besar mengapa ini terjadi.
sumber
Contoh sederhana di Groovy untuk referensi Anda:
sumber