Fungsi bersarang hanyalah sebuah fungsi di dalam fungsi lain, dan terkadang disebut "fungsi dalam". Ada banyak alasan mengapa Anda ingin menggunakan fungsi bersarang, dan kami akan membahas yang paling umum dalam artikel ini Show Cara mendefinisikan fungsi bersarangUntuk mendefinisikan fungsi bersarang, cukup inisialisasi fungsi lain di dalam fungsi dengan menggunakan kata kunci
Keluaran _Seperti yang Anda lihat, fungsi 0 luar, 1 dan 2. Ini adalah kasus penggunaan umum untuk fungsi bersarang–untuk berfungsi sebagai fungsi pembantu kecil untuk fungsi luar yang lebih kompleksAlasan untuk menggunakan fungsi bersarangMeskipun ada banyak alasan yang sah untuk menggunakan fungsi bersarang, di antara yang paling umum adalah fungsi enkapsulasi dan penutupan/pabrik enkapsulasi dataAda kalanya Anda ingin mencegah suatu fungsi atau data yang dapat diaksesnya diakses dari bagian lain kode Anda, sehingga Anda dapat mengenkapsulasinya dalam fungsi lain Saat Anda menyusun fungsi seperti ini, fungsi tersebut tersembunyi dari cakupan global. Karena perilaku ini, enkapsulasi data terkadang disebut sebagai penyembunyian data atau privasi data. Sebagai contoh
Keluaran _Pada kode di atas, fungsi _3 hanya tersedia dari dalam fungsi 4. Jika Anda mencoba memanggil _3 dari luar fungsi, Anda akan mendapatkan kesalahan di atasSebagai gantinya, Anda harus memanggil fungsi _4 seperti itu
Keluaran
PenutupanTetapi apa yang akan terjadi jika fungsi luar mengembalikan fungsi dalam itu sendiri, daripada memanggilnya seperti pada contoh di atas? Berikut ini adalah kondisi yang harus dipenuhi untuk membuat penutupan dengan Python Ini adalah kondisi yang Anda perlukan untuk membuat penutupan dengan Python 1. Harus ada fungsi bersarang Berikut adalah contoh sederhana dari penutupan
Keluaran
Penutupan memungkinkan untuk meneruskan data ke fungsi dalam tanpa terlebih dahulu meneruskannya ke fungsi luar dengan parameter seperti contoh 0 di awal artikel. Mereka juga memungkinkan untuk memanggil fungsi dalam dari luar fungsi luar enkapsulasi. Semua ini dengan manfaat enkapsulasi / penyembunyian data yang disebutkan sebelumnyaSekarang setelah Anda memahami bagaimana dan mengapa menyarangkan fungsi dengan Python, keluarlah dan buat sarang dengan yang terbaik dari mereka IKLAN IKLAN IKLAN Jika artikel ini bermanfaat, tweetlah Belajar kode secara gratis. Kurikulum open source freeCodeCamp telah membantu lebih dari 40.000 orang mendapatkan pekerjaan sebagai pengembang. Memulai Penutupan adalah kombinasi dari fungsi yang dibundel bersama (terlampir) dengan referensi ke keadaan sekitarnya (lingkungan leksikal). Dengan kata lain, sebuah closure memberi Anda akses ke lingkup fungsi luar dari fungsi dalam. Dalam JavaScript, penutupan dibuat setiap kali fungsi dibuat, pada waktu pembuatan fungsi Perhatikan contoh kode berikut
8 membuat variabel lokal bernama 9 dan fungsi bernama 0. Fungsi _0 adalah fungsi dalam yang didefinisikan di dalam 8 dan hanya tersedia di dalam tubuh fungsi 8. Perhatikan bahwa fungsi _0 tidak memiliki variabel lokalnya sendiri. Namun, karena fungsi dalam memiliki akses ke variabel fungsi luar, 0 dapat mengakses variabel 9 yang dideklarasikan dalam fungsi induk, 8Jalankan kode menggunakan tautan JSFiddle ini dan perhatikan bahwa pernyataan 8 dalam fungsi 0 berhasil menampilkan nilai variabel 9, yang dideklarasikan dalam fungsi induknya. Ini adalah contoh pelingkupan leksikal, yang menjelaskan bagaimana parser menyelesaikan nama variabel saat fungsi bersarang. Kata leksikal mengacu pada fakta bahwa pelingkupan leksikal menggunakan lokasi di mana variabel dideklarasikan dalam kode sumber untuk menentukan di mana variabel itu tersedia. Fungsi bersarang memiliki akses ke variabel yang dideklarasikan dalam lingkup luarnyaDalam contoh khusus ini, ruang lingkup disebut ruang lingkup fungsi, karena variabel dapat diakses dan hanya dapat diakses di dalam badan fungsi tempat ia dideklarasikan Biasanya (sebelum ES6), JavaScript hanya memiliki dua jenis cakupan. ruang lingkup fungsi dan ruang lingkup global. Variabel yang dideklarasikan dengan _1 adalah cakupan fungsi atau cakupan global, bergantung pada apakah variabel tersebut dideklarasikan di dalam fungsi atau di luar fungsi. Ini bisa rumit, karena balok dengan kurung kurawal tidak membuat cakupan
Untuk orang-orang dari bahasa lain (mis. g. C, Java) di mana blok membuat ruang lingkup, kode di atas harus menimbulkan kesalahan pada baris 2, karena kita berada di luar ruang lingkup 3 di salah satu blok. Namun, karena blok tidak membuat cakupan untuk 1, pernyataan 1 di sini sebenarnya membuat variabel global. Ada juga yang diperkenalkan di bawah ini yang mengilustrasikan bagaimana hal ini dapat menyebabkan bug yang sebenarnya bila digabungkan dengan penutupanDi ES6, JavaScript memperkenalkan deklarasi _6 dan 7 , yang antara lain seperti , memungkinkan Anda membuat variabel dengan cakupan blok
Intinya, blok akhirnya diperlakukan sebagai cakupan di ES6, tetapi hanya jika Anda mendeklarasikan variabel dengan 6 atau 7. Selain itu, ES6 memperkenalkan modul, yang memperkenalkan cakupan jenis lain. Penutupan dapat menangkap variabel di semua cakupan ini, yang akan kami perkenalkan nantiPerhatikan contoh kode berikut
Menjalankan kode ini memiliki efek yang sama persis dengan contoh sebelumnya dari fungsi 8 di atas. Apa yang berbeda (dan menarik) adalah bahwa fungsi dalam 0 dikembalikan dari fungsi luar sebelum dieksekusiSekilas, sepertinya tidak intuitif bahwa kode ini masih berfungsi. Dalam beberapa bahasa pemrograman, variabel lokal dalam suatu fungsi hanya ada selama durasi eksekusi fungsi tersebut. Setelah _2 selesai dieksekusi, Anda mungkin berharap bahwa variabel 9 tidak lagi dapat diakses. Namun, karena kode masih berfungsi seperti yang diharapkan, hal ini jelas tidak berlaku di JavaScriptAlasannya adalah bahwa fungsi dalam bentuk penutupan JavaScript. Penutupan adalah kombinasi dari fungsi dan lingkungan leksikal di mana fungsi itu dideklarasikan. Lingkungan ini terdiri dari variabel lokal apa pun yang berada dalam ruang lingkup pada saat penutupan dibuat. Dalam hal ini, 4 adalah referensi ke turunan fungsi 5 yang dibuat saat 6 dijalankan. Contoh 5 mempertahankan referensi ke lingkungan leksikalnya, di mana variabel 9 ada. Untuk alasan ini, ketika _4 dipanggil, variabel 9 tetap tersedia untuk digunakan, dan "Mozilla" diteruskan ke 2Inilah contoh yang sedikit lebih menarik—fungsi _ 2
Dalam contoh ini, kami telah mendefinisikan sebuah fungsi 3, yang menggunakan argumen tunggal 3, dan mengembalikan fungsi baru. Fungsi yang dikembalikan mengambil argumen tunggal 5, dan mengembalikan jumlah 3 dan 5Intinya, 2 adalah pabrik fungsi. Itu menciptakan fungsi yang dapat menambahkan nilai spesifik ke argumen mereka. Dalam contoh di atas, pabrik fungsi membuat dua fungsi baru—satu yang menambahkan lima ke argumennya, dan satu lagi yang menambahkan 10 9 dan 0 keduanya penutupan. Mereka berbagi definisi tubuh fungsi yang sama, tetapi menyimpan lingkungan leksikal yang berbeda. Dalam lingkungan leksikal _9, 3 adalah 5, sedangkan dalam lingkungan leksikal untuk 0, 3 adalah 10Penutupan berguna karena memungkinkan Anda mengaitkan data (lingkungan leksikal) dengan fungsi yang beroperasi pada data tersebut. Ini memiliki kesamaan yang jelas dengan pemrograman berorientasi objek, di mana objek memungkinkan Anda untuk mengaitkan data (properti objek) dengan satu atau lebih metode Akibatnya, Anda dapat menggunakan penutupan di mana pun Anda biasanya menggunakan objek hanya dengan satu metode Situasi di mana Anda mungkin ingin melakukan ini sangat umum di web. Sebagian besar kode yang ditulis dalam JavaScript front-end berbasis peristiwa. Anda menentukan beberapa perilaku, lalu melampirkannya ke peristiwa yang dipicu oleh pengguna (seperti klik atau penekanan tombol). Kode dilampirkan sebagai panggilan balik (satu fungsi yang dijalankan sebagai respons terhadap acara tersebut) Misalnya, kita ingin menambahkan tombol ke halaman untuk menyesuaikan ukuran teks. Salah satu cara melakukannya adalah menentukan ukuran font elemen 5 (dalam piksel), lalu menyetel ukuran elemen lain pada halaman (seperti header) menggunakan unit 6 relatif
Tombol ukuran teks interaktif seperti itu dapat mengubah properti 7 dari elemen 5, dan penyesuaian diambil oleh elemen lain di halaman berkat unit relatifInilah JavaScriptnya
9, 0, dan 1 sekarang adalah fungsi yang mengubah ukuran teks isi masing-masing menjadi 12, 14, dan 16 piksel. Anda dapat melampirkannya ke tombol (dalam hal ini hyperlink) seperti yang ditunjukkan pada contoh kode berikut
Jalankan kode menggunakan JSFiddle Bahasa seperti Java memungkinkan Anda mendeklarasikan metode sebagai privat, artinya metode tersebut hanya dapat dipanggil oleh metode lain di kelas yang sama JavaScript, sebelum kelas, tidak memiliki cara mendeklarasikan asli, tetapi dimungkinkan untuk meniru metode pribadi menggunakan penutupan. Metode pribadi tidak hanya berguna untuk membatasi akses ke kode. Mereka juga menyediakan cara yang ampuh untuk mengelola namespace global Anda Kode berikut mengilustrasikan cara menggunakan closure untuk mendefinisikan fungsi publik yang dapat mengakses fungsi dan variabel privat. Perhatikan bahwa penutupan ini mengikuti Pola Desain Modul
Dalam contoh sebelumnya, setiap penutupan memiliki lingkungan leksikalnya sendiri. Namun di sini, ada lingkungan leksikal tunggal yang digunakan bersama oleh ketiga fungsi tersebut. 2, 3, dan 4Lingkungan leksikal bersama dibuat di badan fungsi anonim, yang dijalankan segera setelah didefinisikan (juga dikenal sebagai IIFE). Lingkungan leksikal berisi dua item pribadi. sebuah variabel bernama _5, dan sebuah fungsi bernama 6. Anda tidak dapat mengakses anggota pribadi ini dari luar fungsi anonim. Sebagai gantinya, Anda dapat mengaksesnya menggunakan tiga fungsi publik yang dikembalikan dari pembungkus anonimKetiga fungsi publik tersebut merupakan closure yang memiliki lingkungan leksikal yang sama. Berkat pelingkupan leksikal JavaScript, mereka masing-masing memiliki akses ke variabel 5 dan fungsi 6 0Perhatikan bagaimana kedua penghitung mempertahankan independensinya satu sama lain. Setiap penutupan mereferensikan versi yang berbeda dari variabel 5 melalui penutupannya sendiri. Setiap kali salah satu penghitung dipanggil, lingkungan leksikalnya berubah dengan mengubah nilai variabel ini. Perubahan pada nilai variabel di satu penutupan tidak memengaruhi nilai di penutupan lainnyaCatatan. Menggunakan penutupan dengan cara ini memberikan manfaat yang biasanya diasosiasikan dengan pemrograman berorientasi objek. Secara khusus, penyembunyian dan enkapsulasi data Setiap penutupan memiliki tiga cakupan
Kesalahan umum adalah tidak menyadari bahwa dalam kasus di mana fungsi luar itu sendiri adalah fungsi bersarang, akses ke ruang lingkup fungsi luar mencakup ruang lingkup terlampir dari fungsi luar — secara efektif membuat rangkaian ruang lingkup fungsi. Untuk mendemonstrasikan, perhatikan kode contoh berikut 1Anda juga dapat menulis tanpa fungsi anonim 2Dalam contoh di atas, ada serangkaian fungsi bersarang, yang semuanya memiliki akses ke lingkup fungsi luar. Dalam konteks ini, kita dapat mengatakan bahwa penutupan memiliki akses ke semua cakupan fungsi luar Penutupan dapat menangkap variabel dalam cakupan blok dan cakupan modul juga. Misalnya, berikut ini membuat penutupan atas variabel cakupan blok 5 3Penutupan modul bisa lebih menarik 4Di sini, modul mengekspor sepasang fungsi getter-setter, yang menutup variabel cakupan modul 3. Bahkan ketika _3 tidak dapat diakses langsung dari modul lain, itu dapat dibaca dan ditulis dengan fungsi 5Penutupan juga dapat menutup nilai yang diimpor, yang dianggap sebagai pengikat langsung, karena ketika nilai asli berubah, nilai yang diimpor juga berubah. 6 7 8Sebelum pengenalan kata kunci _6, masalah umum dengan penutupan terjadi saat Anda membuatnya di dalam satu lingkaran. Untuk mendemonstrasikan, perhatikan kode contoh berikut _9 0Coba jalankan kode di JSFiddle Larik _4 mendefinisikan tiga petunjuk bermanfaat, masing-masing terkait dengan ID bidang masukan dalam dokumen. Loop menggilir definisi ini, mengaitkan peristiwa 5 ke masing-masing yang menunjukkan metode bantuan terkaitJika Anda mencoba kode ini, Anda akan melihat bahwa itu tidak berfungsi seperti yang diharapkan. Apa pun bidang yang Anda fokuskan, pesan tentang usia Anda akan ditampilkan Alasannya adalah karena fungsi yang ditetapkan ke 5 adalah penutupan; . Tiga penutupan telah dibuat oleh loop, tetapi masing-masing berbagi lingkungan leksikal tunggal yang sama, yang memiliki variabel dengan nilai yang berubah ( 8). Ini karena variabel _8 dideklarasikan dengan 1 dan dengan demikian memiliki ruang lingkup fungsi karena mengangkat. Nilai _01 ditentukan saat callback 5 dijalankan. Karena loop telah berjalan pada saat itu, objek variabel 8 (dibagi oleh ketiga penutupan) dibiarkan menunjuk ke entri terakhir dalam daftar 4Salah satu solusi dalam hal ini adalah menggunakan lebih banyak penutupan. khususnya, untuk menggunakan fungsi pabrik seperti yang dijelaskan sebelumnya 1Jalankan kode menggunakan tautan JSFiddle ini Ini bekerja seperti yang diharapkan. Alih-alih semua panggilan balik berbagi satu lingkungan leksikal, fungsi 05 membuat lingkungan leksikal baru untuk setiap panggilan balik, di mana 06 merujuk ke string yang sesuai dari larik 4Salah satu cara lain untuk menulis di atas menggunakan penutupan anonim adalah 2Jika Anda tidak ingin menggunakan lebih banyak penutupan, Anda dapat menggunakan kata kunci 6 atau 7 3Contoh ini menggunakan 7 alih-alih 1, sehingga setiap penutupan mengikat variabel cakupan blok, artinya tidak diperlukan penutupan tambahanAlternatif lain bisa menggunakan _12 untuk mengulang array 4 dan melampirkan pendengar ke setiap 14, seperti yang ditunjukkan _4Seperti disebutkan sebelumnya, setiap instance fungsi mengelola ruang lingkup dan penutupannya sendiri. Oleh karena itu, tidak bijaksana untuk tidak perlu membuat fungsi di dalam fungsi lain jika penutupan tidak diperlukan untuk tugas tertentu, karena akan berdampak negatif pada kinerja skrip baik dalam hal kecepatan pemrosesan dan konsumsi memori Misalnya, saat membuat objek/kelas baru, metode biasanya harus dikaitkan dengan prototipe objek daripada didefinisikan ke dalam konstruktor objek. Alasannya adalah setiap kali konstruktor dipanggil, metode akan dipindahkan (yaitu, untuk setiap pembuatan objek) Pertimbangkan kasus berikut 5Karena kode sebelumnya tidak mengambil manfaat dari penggunaan closure dalam contoh khusus ini, kita dapat menulis ulang untuk menghindari penggunaan closure sebagai berikut 6Namun, mendefinisikan ulang prototipe tidak disarankan. Contoh berikut malah ditambahkan ke prototipe yang ada 7Dalam dua contoh sebelumnya, prototipe yang diwariskan dapat digunakan bersama oleh semua objek dan definisi metode tidak perlu muncul di setiap pembuatan objek. Lihat Pewarisan dan rantai prototipe untuk lebih lanjut Apa saja 3 jenis fungsi dalam JavaScript?Ada 3 cara penulisan fungsi di JavaScript. . Deklarasi Fungsi Ekspresi Fungsi Fungsi Panah Bagaimana cara memanggil fungsi 3 kali dalam JavaScript?Untuk menjalankan fungsi berkali-kali setelah waktu yang tetap, kami menggunakan beberapa fungsi. Metode JavaScript setInterval() . Metode ini memanggil fungsi pada interval tertentu (dalam ms). Metode ini akan terus memanggil fungsi hingga clearInterval() dijalankan, atau jendela ditutup.
Bagaimana Anda membuat fungsi bersarang di JavaScript?Tulis satu fungsi di dalam fungsi lain. Lakukan panggilan ke fungsi dalam di pernyataan pengembalian fungsi luar. Sebut saja fun(a)(b) di mana a adalah parameter ke luar dan b ke fungsi dalam. Terakhir, kembalikan output gabungan dari fungsi bersarang
Apa fungsi bersarang di JavaScript?Karena fungsi bersarang adalah penutupan, ini berarti bahwa fungsi bersarang dapat "mewarisi" argumen dan variabel dari fungsi yang memuatnya . Dengan kata lain, inner function berisi cakupan dari outer function. Untuk meringkas. Fungsi bagian dalam hanya dapat diakses dari pernyataan di fungsi bagian luar. |