Kata pengantar
Dalam ecmascript, ada dua metode yang paling umum digunakan untuk membuat objek fungsi, yaitu menggunakan ekspresi fungsi atau menggunakan deklarasi fungsi. Dalam hal ini, spesifikasi ecmascript memperjelas bahwa deklarasi fungsi harus selalu membawa pengidentifikasi, yang merupakan apa yang kita sebut nama fungsi, dan ekspresi fungsi dapat dihilangkan. Mari kita lihat perkenalan terperinci tentang perbedaan antara keduanya.
Apa itu Deklarasi Fungsi?
Deklarasi fungsi dapat mendefinisikan variabel fungsi yang disebutkan tanpa menetapkan nilai ke variabel. Fungsi Deklarasi adalah struktur independen yang tidak dapat bersarang dalam modul non-fungsional. Ini dapat dibandingkan dengan deklarasi variabel. Sama seperti deklarasi variabel harus dimulai dengan "var", deklarasi fungsi harus dimulai dengan "fungsi".
Misalnya
batang fungsi () {return 3;}ECMA 5 (13.0) Definisi Sintaks:
function Identifier ( FormalParameterList[opt] ) { FunctionBody }
Nama fungsi tersedia dalam ruang lingkup mereka sendiri dan ruang lingkup induk (jika tidak fungsi tidak akan tersedia).
batang fungsi () {return 3;} bar () // 3bar // fungsiApa itu ekspresi fungsi?
Ekspresi fungsi mendefinisikan fungsi sebagai bagian dari pernyataan ekspresi (biasanya penugasan variabel). Fungsi yang ditentukan oleh ekspresi fungsi dapat dinamai atau anonim. Ekspresi fungsi tidak dapat dimulai dengan "fungsi" (contoh-contoh mandiri berikut harus dilampirkan dalam tanda kurung).
Misalnya
// Fungsi Anonim ExpressionVar a = function () {return 3;} // bernama Function ExpressionVar A = Function Bar () {return 3;} // Mandiri memohon ekspresi fungsi (function wayshello () {alert ("Hello!");}) ();ECMA 5 (13.0) Definisi Sintaks:
function Identifieropt ( FormalParameterList[opt] ) { FunctionBody }
(Definisi ini terasa tidak lengkap karena mengabaikan suatu kondisi: pernyataan periferal adalah ekspresi dan tidak dimulai dengan "fungsi")
Nama fungsi (jika ada) tidak tersedia di luar ruang lingkup (dibandingkan dengan deklarasi fungsi).
Jadi apa itu pernyataan fungsi?
Pernyataan fungsi terkadang merupakan cara deklarasi fungsi lain. Tetapi Kangax menunjukkan bahwa dalam Mozilla, pernyataan fungsi adalah perpanjangan dari deklarasi fungsi, yang memungkinkan pernyataan deklarasi fungsi digunakan di mana saja yang memungkinkan penggunaan pernyataan. Namun, pernyataan fungsi bukan standar sekarang, sehingga tidak disarankan untuk digunakan dalam pengembangan produk.
Mari kita mulai dengan beberapa tes kecil. Tebak apa yang akan muncul dalam situasi berikut?
Pertanyaan 1:
function foo () {function bar () {return 3; } return bar (); function bar () {return 8; }} alert (foo ());Pertanyaan 2:
function foo () {var bar = function () {return 3; }; return bar (); var bar = function () {return 8; };} alert (foo ());Pertanyaan 3:
alert (foo ()); function foo () {var bar = function () {return 3; }; return bar (); var bar = function () {return 8; };}Pertanyaan 4:
function foo () {return bar (); var bar = function () {return 3; }; var bar = function () {return 8; };} alert (foo ());Jika jawaban Anda bukan 8, 3, 3 dan [Ketik Kesalahan: Bar bukan fungsi], maka lanjutkan membaca ... (bahkan jika Anda menjawab dengan benar, Anda harus terus membaca)
Sekarang mari kita jelaskan tes sebelumnya.
Pertanyaan 1 menggunakan deklarasi fungsi, yang berarti mereka diangkat ...
Tunggu, apa itu mengangkat?
Berikut adalah kutipan dari Ben Cherry: "Deklarasi fungsi dan variabel fungsi biasanya dipindahkan ('diangkat') ke bagian atas ruang lingkup saat ini oleh juru bahasa JavaScript."
Ketika deklarasi fungsi dipromosikan, seluruh badan fungsi akan dipromosikan sesuai, sehingga kode pertanyaan 1 berjalan seperti ini setelah dijelaskan oleh penerjemah:
// ** Urutan pemrosesan yang disimulasikan untuk pertanyaan 1 ** fungsi foo () {// tentukan batang sekali batang fungsi () {return 3; } // mendefinisikan kembali bilah fungsi TI () {return 8; } // mengembalikan bilah pengembalian doa (); // 8} alert (foo ());Namun, kita sering diberitahu bahwa kode di balik pernyataan pengembalian tidak dapat berjalan ...
Selama pelaksanaan JavaScript, ada dua konsep: konteks (ECMA 5 memecahnya menjadi lingkungan leksikal, lingkungan variabel dan pengikat this) dan proses (serangkaian pernyataan yang disebut berurutan). Ketika program memasuki domain eksekusi, deklarasi menyebabkan variabel -lingkungan. Mereka berbeda dari pernyataan (seperti pengembalian) dan tidak mengikuti aturan menjalankan pernyataan.
Akankah ekspresi fungsi dipromosikan?
Itu tergantung pada ekspresi. Misalnya, ungkapan pertama dalam pertanyaan 2:
var bar = function () {return 3;};(Var batang) di sebelah kiri tanda yang sama adalah deklarasi variabel. Deklarasi variabel akan dipromosikan, tetapi ekspresi penugasan tidak akan. Jadi ketika bar dipromosikan, penerjemah akan diinisialisasi seperti ini: var bar = tidak terdefinisi. Definisi fungsi itu sendiri tidak akan dipromosikan.
(ECMA 5 12.2 Variabel dengan InitialZier ditugaskan oleh penugasan EXPRESSIon ketika variabelestatement dieksekusi, bukan saat variabel dibuat.)
Oleh karena itu, kode pertanyaan 2 akan dijalankan dalam urutan berikut:
// ** Urutan pemrosesan yang disimulasikan untuk pertanyaan 2 ** fungsi foo () {// Deklarasi untuk setiap fungsi ekspresi var bar = tidak terdefinisi; var bar = tidak terdefinisi; // Ekspresi fungsi pertama dieksekusi bar = fungsi () {return 3; }; // fungsi yang dibuat oleh ekspresi fungsi pertama dipanggil batang pengembalian (); // Ekspresi fungsi kedua tidak terjangkau} peringatan (foo ()); // 3Anda dapat mengatakan bahwa ini dapat dijelaskan, tetapi jawaban untuk pertanyaan 3 salah. Saya akan melaporkan kesalahan saat menjalankan Firebug.
Simpan kode dalam file HTML dan coba jalankan di Firefox. Atau jalankan di IE8, Chrome, atau Safari Console. Jelas, konsol Firebug tidak akan mempromosikan fungsi saat menjalankan kode dalam lingkup "global" (sebenarnya tidak global, tetapi cakupan "firebug" yang unik - cukup coba jalankan "jendela == ini" di konsol Firebug).
Pertanyaan 3 dan Pertanyaan 1 memiliki logika yang sama. Kali ini fungsi foo dipromosikan.
Pertanyaan 4 sangat sederhana, tidak ada peningkatan fungsi sama sekali ...
Dapat dikatakan itu, tetapi jika tidak ada perbaikan sama sekali, TypeError akan menjadi "bilah yang tidak didefinisikan" alih -alih "bar bukan fungsi". Memang tidak ada peningkatan fungsi dalam contoh ini, tetapi ada peningkatan variabel. Oleh karena itu, bar dinyatakan di awal, tetapi nilainya tidak ditentukan. Kode lain dieksekusi secara berurutan.
// ** Urutan pemrosesan yang disimulasikan untuk pertanyaan 4 ** fungsi foo () {// Deklarasi untuk setiap fungsi ekspresi var bar = tidak terdefinisi; var bar = tidak terdefinisi; return bar (); // typeError: "Bar tidak didefinisikan" // Tidak ada ekspresi fungsi yang tercapai} waspada (foo ());Apa lagi yang harus Anda perhatikan?
Pejabat tersebut melarang penggunaan deklarasi fungsi dalam modul non-fungsional (seperti IF). Namun, semua browser mendukungnya, tetapi penjelasan mereka berbeda.
Misalnya, cuplikan kode berikut akan melempar kesalahan dalam Firefox 3.6 karena menafsirkan deklarasi fungsi sebagai pernyataan fungsi (lihat di atas), jadi X tidak didefinisikan. Tetapi di IE8, Chrome 5 dan Safari 5, fungsi X akan dikembalikan (sama seperti Deklarasi Fungsi Standar).
function foo () {if (false) {function x () {}; } return x;} alert (foo ());Dapat dilihat bahwa menggunakan deklarasi fungsi dapat menyebabkan kebingungan, jadi apakah ada keuntungan?
Anda mungkin mengatakan bahwa deklarasi fungsi cukup longgar - jika Anda mencoba menggunakan fungsi sebelum deklarasi, promosi memang dapat memperbaiki urutan sehingga fungsi dapat dipanggil dengan benar. Tetapi kelonggaran semacam ini tidak kondusif untuk pengkodean yang ketat, dan dari perspektif jangka panjang, cenderung mempromosikan daripada mencegah kecelakaan. Lagi pula, ada alasan pemrogram mengatur pernyataan dalam urutan tertentu.
Jadi, apakah ada alasan lain untuk mendukung ekspresi fungsi?
Bagaimana menurutmu?
1) Deklarasi fungsi terasa seperti meniru deklarasi metode gaya Java, tetapi metode Java tidak sama dengan JavaScript. Dalam JavaScript, fungsi adalah objek hidup dengan nilai -nilai. Metode Java hanyalah penyimpanan metadata. Dua potong kode berikut menentukan fungsi, tetapi hanya ekspresi fungsi yang terlihat seperti objek yang dibuat.
// fungsi deklarasi fungsi add (a, b) {return a + b}; // function ekspresivar add = function (a, b) {return a + b};2) Ekspresi fungsi memiliki lebih banyak kegunaan. Deklarasi fungsi hanya dapat ada di yatim piatu sebagai "pernyataan". Yang bisa dilakukan hanyalah membuat variabel objek di bawah ruang lingkup saat ini. Ekspresi fungsi, menurut definisi, adalah bagian dari struktur besar. Jika Anda ingin membuat fungsi anonim, tambahkan fungsi ke prototipe, atau menggunakan fungsi sebagai properti dari objek lain, Anda dapat menggunakan ekspresi fungsi. Setiap kali Anda menggunakan aplikasi canggih, seperti kari atau menyusun, Anda menggunakan ekspresi fungsi saat membuat fungsi baru. Ekspresi fungsi dan pemrograman fungsional tidak dapat dipisahkan.
// Function ExpressionVar Sayshello = Alert.Curry ("Hello!");Apakah ada kelemahan dalam ekspresi fungsi?
Ekspresi fungsi menciptakan sebagian besar fungsi anonim. Misalnya, fungsi berikut adalah anonim, hari ini hanyalah referensi ke fungsi anonim:
var hari ini = function () {return new date ()}Apakah ini bermasalah? Tidak dalam kebanyakan kasus, tetapi seperti yang ditunjukkan Nick Fitzgerald, men -debug fungsi anonim bisa menjengkelkan. Dia merekomendasikan penggunaan Function Expressions (NFE) sebagai ruang kerja:
var hari ini = fungsi hari ini () {return new date ()}Namun, seperti yang dikatakan Asen Bozhilov (dan dokumentasi Kangax) tidak dapat dieksekusi dengan benar di bawah IE9.
sebagai kesimpulan
Deklarasi fungsi yang ditempatkan secara acak menyesatkan dan jarang (jika ada) situasi, dan menetapkan nilai ke variabel dengan ekspresi fungsi tidak dapat menggantikan deklarasi fungsi. Tetapi jika diperlukan deklarasi fungsi, meletakkannya di bagian atas ruang lingkup dapat mengurangi kebingungan. Jangan pernah menempatkan deklarasi fungsi dalam pernyataan IF.
Setelah mengatakan begitu banyak, deklarasi fungsi mungkin berguna dalam situasi Anda sendiri. Itu bukan apa -apa. Dogma peran berbahaya dan sering menyebabkan kode dikalahkan di sekitar semak. Lebih penting lagi, Anda memahami konsep tersebut sehingga Anda dapat memutuskan metode mana yang akan membuat fungsi berdasarkan situasi Anda sendiri. Di atas adalah seluruh konten artikel ini. Saya harap artikel ini akan membantu semua orang dalam hal ini.