Saya membaca beberapa posting tentang penutupan dan melihat ini di mana-mana, tetapi tidak ada penjelasan yang jelas tentang cara kerjanya - setiap kali saya hanya diminta untuk menggunakannya ...:
// Create a new anonymous function, to use as a wrapper
(function(){
// The variable that would, normally, be global
var msg = "Thanks for visiting!";
// Binding a new function to a global object
window.onunload = function(){
// Which uses the 'hidden' variable
alert( msg );
};
// Close off the anonymous function and execute it
})();
Ok saya melihat bahwa kita akan membuat fungsi anonim baru dan kemudian menjalankannya. Jadi setelah itu kode sederhana ini akan berfungsi (dan itu memang):
(function (msg){alert(msg)})('SO');
Pertanyaan saya adalah sihir apa yang terjadi di sini? Saya berpikir ketika saya menulis:
(function (msg){alert(msg)})
maka fungsi tanpa nama baru akan dibuat seperti fungsi "" (msg) ...
tapi mengapa ini tidak berhasil?
(function (msg){alert(msg)});
('SO');
Mengapa harus di baris yang sama?
Bisakah Anda menunjukkan saya beberapa posting atau memberi saya penjelasan?
(function (msg){alert(msg)})('SO');
bekerja sepenuhnya dengan sendirinya. Ini tidak ada hubungannya dengan fungsi anonim lain yang Anda poskan sebelumnya. Mereka adalah dua fungsi anonim yang sepenuhnya terpisah. Anda harus segera menjalankan fungsi anonim karena tidak memiliki nama dan tidak dapat direferensikan setelahnya.Jawaban:
Jatuhkan titik koma setelah definisi fungsi.
Di atas harus bekerja.
Halaman DEMO: https://jsfiddle.net/e7ooeq6m/
Saya telah membahas pola semacam ini di pos ini:
jQuery dan $ pertanyaan
EDIT:
Jika Anda melihat spesifikasi skrip ECMA , ada 3 cara Anda dapat mendefinisikan suatu fungsi. (Halaman 98, Bagian 13 Definisi Fungsi)
1. Menggunakan Function constructor
2. Menggunakan deklarasi Fungsi.
3. Ekspresi Fungsi
Jadi Anda mungkin bertanya, apa perbedaan antara deklarasi dan ekspresi?
Dari spesifikasi Script ECMA:
Jika Anda perhatikan, 'pengidentifikasi' adalah opsional untuk ekspresi fungsi. Dan ketika Anda tidak memberikan pengenal, Anda membuat fungsi anonim. Itu tidak berarti bahwa Anda tidak dapat menentukan pengidentifikasi.
Ini berarti mengikuti adalah valid.
Poin penting yang perlu diperhatikan adalah Anda dapat menggunakan 'mySum' hanya di dalam tubuh fungsi mySum, bukan di luar. Lihat contoh berikut:
Demo Langsung
Bandingkan ini dengan
Berbekal pengetahuan ini, mari kita coba menganalisis kode Anda.
Ketika Anda memiliki kode seperti,
Anda membuat ekspresi fungsi. Dan Anda bisa menjalankan ekspresi fungsi ini dengan membungkusnya di dalam tanda kurung.
sumber
Ini disebut fungsi yang dipanggil sendiri.
Apa yang Anda lakukan saat menelepon
(function(){})
mengembalikan objek fungsi. Ketika Anda menambahkannya()
, itu dipanggil dan apa pun di tubuh dieksekusi. Yang;
menunjukkan akhir pernyataan, itu sebabnya doa ke-2 gagal.sumber
Satu hal yang saya anggap membingungkan adalah "()" adalah operator pengelompokan.
Inilah fungsi dasar Anda yang dideklarasikan.
Ex. 1:
Fungsi adalah objek, dan dapat dikelompokkan. Jadi mari kita melempar orangtua di sekitar fungsi.
Ex. 2:
Sekarang alih-alih mendeklarasikan dan langsung memanggil fungsi yang sama, kita dapat menggunakan substitusi dasar untuk mendeklarasikannya seperti kita menyebutnya.
Ex. 3.
Akhirnya, kami tidak membutuhkan foo tambahan itu karena kami tidak menggunakan nama untuk memanggilnya! Fungsinya bisa anonim.
Ex. 4.
Untuk menjawab pertanyaan Anda, lihat kembali Contoh 2. Baris pertama Anda menyatakan beberapa fungsi tanpa nama dan mengelompokkannya, tetapi tidak menyebutnya. Baris kedua mengelompokkan string. Keduanya tidak melakukan apa pun. (Contoh pertama Vincent.)
Tapi
sumber
Fungsi anonim bukanlah fungsi dengan nama "". Ini hanyalah sebuah fungsi tanpa nama.
Seperti nilai lain dalam JavaScript, fungsi tidak perlu nama yang akan dibuat. Meskipun jauh lebih berguna untuk benar-benar mengikatnya ke nama sama seperti nilai lainnya.
Tetapi seperti nilai lainnya, Anda terkadang ingin menggunakannya tanpa mengikatnya ke nama. Itulah pola yang membangkitkan semangat.
Ini adalah fungsi dan angka, tidak terikat, mereka tidak melakukan apa-apa dan tidak pernah dapat digunakan:
Jadi kita harus menyimpannya dalam variabel untuk dapat menggunakannya, sama seperti nilai lainnya:
Anda juga dapat menggunakan gula sintaksis untuk mengikat fungsi ke variabel:
Tetapi jika penamaan mereka tidak diperlukan dan akan menyebabkan lebih banyak kebingungan dan lebih sedikit keterbacaan, Anda bisa langsung menggunakannya.
Di sini, fungsi saya dan nomor saya tidak terikat pada variabel, tetapi mereka masih dapat digunakan.
Mengatakan seperti ini, sepertinya fungsi self-invaging tidak memiliki nilai nyata. Tetapi Anda harus ingat bahwa pembatas ruang lingkup JavaScript adalah fungsi dan bukan blok ({}).
Jadi fungsi self-invoking sebenarnya memiliki arti yang sama dengan blok C ++, C # atau Java. Yang berarti bahwa variabel yang dibuat di dalam tidak akan "bocor" di luar ruang lingkup. Ini sangat berguna dalam JavaScript agar tidak mencemari ruang lingkup global.
sumber
Itu hanya cara kerja JavaScript. Anda dapat mendeklarasikan fungsi bernama:
Dan menyebutnya:
Atau, Anda dapat mendeklarasikan fungsi anonim:
Dan sebut itu:
Atau, Anda tidak bisa mengikat fungsi ke nama:
Fungsi juga dapat mengembalikan fungsi:
Tidak ada artinya bahwa setiap variabel yang didefinisikan dengan "var" dalam tubuh
make_foo
akan ditutup oleh setiap fungsi yang dikembalikan olehmake_foo
. Ini adalah penutupan, dan itu berarti bahwa setiap perubahan yang dilakukan pada nilai oleh satu fungsi akan terlihat oleh yang lain.Ini memungkinkan Anda merangkum informasi, jika Anda menginginkan:
Hanya saja hampir setiap bahasa pemrograman tetapi Java berfungsi.
sumber
Kode yang Anda tunjukkan,
terdiri dari dua pernyataan. Yang pertama adalah ekspresi yang menghasilkan objek fungsi (yang kemudian akan menjadi sampah yang dikumpulkan karena tidak disimpan). Yang kedua adalah ekspresi yang menghasilkan string. Untuk menerapkan fungsi ke string, Anda harus meneruskan string sebagai argumen ke fungsi ketika itu dibuat (yang juga Anda tunjukkan di atas), atau Anda harus benar-benar menyimpan fungsi dalam variabel, sehingga Anda bisa menerapkannya di lain waktu, di waktu luang Anda. Seperti itu:
Perhatikan bahwa dengan menyimpan fungsi anonim (fungsi lambda) dalam variabel, Anda secara efektif memberinya nama. Karenanya Anda dapat mendefinisikan fungsi biasa:
sumber
Dalam ringkasan komentar sebelumnya:
ketika tidak ditugaskan ke variabel, menghasilkan kesalahan sintaksis. Kode diuraikan sebagai pernyataan fungsi (atau definisi), yang menjadikan tanda kurung tutup secara sintaksis salah. Menambahkan tanda kurung di sekitar bagian fungsi memberi tahu juru bahasa (dan programmer) bahwa ini adalah ekspresi fungsi (atau doa), seperti dalam
Ini adalah fungsi self-invaging, artinya ia dibuat secara anonim dan berjalan segera karena doa terjadi di baris yang sama di mana ia dinyatakan. Fungsi diri memohon hal ini ditunjukkan dengan sintaks yang akrab memanggil fungsi tanpa argumen, ditambah menambahkan tanda kurung di sekitar nama fungsi:
(myFunction)();
.Ada sintaks fungsi JavaScript diskusi SO yang baik .
sumber
Jawaban ini tidak sepenuhnya terkait dengan pertanyaan, tetapi Anda mungkin tertarik untuk mengetahui bahwa fitur sintaksis semacam ini tidak khusus untuk fungsi. Misalnya, kita selalu dapat melakukan sesuatu seperti ini:
Terkait dengan fungsi. Karena mereka adalah objek, yang mewarisi dari Function.prototype, kita dapat melakukan hal-hal seperti:
Dan Anda tahu, kita bahkan tidak perlu mengelilingi fungsi dengan tanda kurung untuk menjalankannya. Lagi pula, selama kita mencoba untuk menetapkan hasil ke variabel.
Satu hal lain yang dapat Anda lakukan dengan fungsi, segera setelah Anda mendeklarasikannya, adalah untuk memanggil
new
operator atas mereka dan mendapatkan objek. Berikut ini adalah setara:sumber
Ada satu lagi fungsi yang dimiliki fungsi JavaScript. Jika Anda ingin memanggil fungsi anonim yang sama secara rekursif.
sumber
Pemahaman saya tentang pertanyaan penanya adalah sedemikian rupa sehingga:
Bagaimana cara kerja sihir ini:
Saya mungkin salah. Namun, praktik yang biasa dilakukan orang adalah:
Alasannya adalah sedemikian sehingga JavaScript tanda kurung AKA
()
, tidak dapat berisi pernyataan dan ketika parser menemukan kata kunci fungsi, ia tahu untuk menguraikannya sebagai ekspresi fungsi dan bukan deklarasi fungsi.Sumber: posting blog Ekspresi Fungsi Segera Dibatalkan (IIFE)
sumber
contoh tanpa tanda kurung:
(Ini adalah satu-satunya penggunaan void, afaik)
atau
atau
bekerja juga. yang
void
menyebabkan ekspresi untuk mengevaluasi, serta tugas dan bang. yang terakhir bekerja dengan~
,+
,-
,delete
,typeof
, beberapa operator unary (void
satu juga). tidak bekerja adalah penyebab++
,--
karena persyaratan variabel.istirahat baris tidak perlu.
sumber
delete
bekerja. bahkan dengan'use strict';
. ini juga berfungsi:delete (3 + 4);
Ini adalah fungsi anonim yang dijalankan sendiri. Set kurung pertama berisi ekspresi yang akan dieksekusi, dan set kedua kurung mengeksekusi ekspresi tersebut.
Peter Michaux membahas perbedaan dalam Sepasang Kurung Yang Penting .
Ini adalah konstruksi yang berguna ketika mencoba untuk menyembunyikan variabel dari namespace induk. Semua kode di dalam fungsi terkandung dalam ruang lingkup fungsi pribadi, artinya tidak dapat diakses sama sekali dari luar fungsi, membuatnya benar-benar pribadi.
Lihat:
sumber
Sudut pandang lain
Pertama, Anda dapat mendeklarasikan fungsi anonim:
Maka Anda menyebutnya:
Karena foo = function (msg) {alert (msg);} sehingga Anda dapat mengganti foo sebagai:
Tetapi Anda harus membungkus seluruh fungsi anonim Anda di dalam sepasang kawat gigi untuk menghindari kesalahan sintaks dari mendeklarasikan fungsi saat parsing. Lalu kita punya,
Dengan cara ini, mudah dimengerti bagi saya.
sumber
Ketika Anda melakukannya:
Anda mengakhiri fungsi sebelumnya
('SO')
karena titik koma. Jika Anda hanya menulis:Itu akan berhasil.
Contoh kerja: http://jsfiddle.net/oliverni/dbVjg/
sumber
Alasan sederhana mengapa itu tidak berhasil bukan karena
;
menunjukkan akhir dari fungsi anonim. Itu karena tanpa()
di akhir panggilan fungsi, itu bukan panggilan fungsi. Itu adalah,Jika Anda memanggil
result = help();
ini adalah panggilan ke suatu fungsi dan akan mengembalikan true.Jika Anda menelepon
result = help;
ini bukan panggilan. Ini adalah tugas di mana bantuan diperlakukan seperti data yang akan ditugaskan untuk hasil.Apa yang Anda lakukan adalah mendeklarasikan / membuat instance fungsi anonim dengan menambahkan tanda titik koma,
dan kemudian mencoba menyebutnya dalam pernyataan lain hanya dengan menggunakan tanda kurung ... Jelas karena fungsi tidak memiliki nama, tetapi ini tidak akan berfungsi:
Penerjemah melihat tanda kurung pada baris kedua sebagai instruksi / pernyataan baru, dan karenanya tidak berfungsi, bahkan jika Anda melakukannya seperti ini:
Masih tidak berfungsi, tetapi berfungsi saat Anda menghapus titik koma karena penerjemah mengabaikan spasi putih dan gerbong dan melihat kode lengkap sebagai satu pernyataan.
Kesimpulan: panggilan fungsi bukan panggilan fungsi tanpa
()
di akhir kecuali dalam kondisi tertentu seperti dipanggil oleh fungsi lain, yaitu, onload = 'bantuan' akan menjalankan fungsi bantuan meskipun tanda kurung tidak dimasukkan. Saya percaya setTimeout dan setInterval juga memungkinkan pemanggilan fungsi jenis ini juga, dan saya juga percaya bahwa penerjemah menambahkan tanda kurung di belakang layar bagaimanapun juga yang membawa kita kembali ke "pemanggilan fungsi bukan pemanggilan fungsi tanpa tanda kurung".sumber
Ini adalah metode umum menggunakan fungsi anonim sebagai penutup yang digunakan banyak kerangka kerja JavaScript.
Fungsi ini dipanggil secara otomatis ketika kode dikompilasi.
Jika menempatkan
;
pada baris pertama, kompilator memperlakukannya sebagai dua baris yang berbeda. Jadi Anda tidak bisa mendapatkan hasil yang sama seperti di atas.Ini juga dapat ditulis sebagai:
Untuk detail lebih lanjut, lihatlah pada Fungsi JavaScript / Anonim .
sumber
Fungsi anonim adalah fungsi yang secara dinamis dideklarasikan pada saat runtime. Mereka disebut fungsi anonim karena mereka tidak diberi nama dengan cara yang sama seperti fungsi normal.
Fungsi anonim dideklarasikan menggunakan operator fungsi alih-alih deklarasi fungsi. Anda dapat menggunakan operator fungsi untuk membuat fungsi baru di mana pun valid untuk meletakkan ekspresi. Misalnya Anda dapat mendeklarasikan fungsi baru sebagai parameter untuk panggilan fungsi atau untuk menetapkan properti objek lain.
Berikut adalah contoh khas dari fungsi bernama:
function flyToTheMoon () {alert ("Zoom! Zoom! Zoom!"); } terbang ke bulan(); Berikut ini contoh yang sama dibuat sebagai fungsi anonim:
var flyToTheMoon = function () {alert ("Zoom! Zoom! Zoom!"); } terbang ke bulan();
Untuk detail silakan baca di sini:
http://helephant.com/2008/08/23/javascript-anonymous-functions/
sumber
IIFE hanya mengelompokkan fungsi dan menyembunyikan
msg
variabel agar tidak "mencemari" namespace global. Pada kenyataannya, tetap sederhana dan lakukan seperti di bawah ini kecuali Anda membangun situs web miliaran dolar.Anda dapat namespace
msg
properti Anda menggunakan Pola Penyingkapan Modul seperti:sumber
Fungsi anonim dimaksudkan untuk menangani satu-shot di mana Anda mendefinisikan fungsi dengan cepat sehingga menghasilkan output dari Anda dari input yang Anda berikan. Kecuali Anda tidak memberikan input. Alih-alih, Anda menulis sesuatu di baris kedua ('SO'); - pernyataan independen yang tidak ada hubungannya dengan fungsi. Apa yang kamu harapkan? :)
sumber
var foo = function() {};
. Segala sesuatu yang lain baik-baik saja.