Kode ini selalu berfungsi, bahkan di berbagai browser:
function fooCheck() {
alert(internalFoo()); // We are using internalFoo() here...
return internalFoo(); // And here, even though it has not been defined...
function internalFoo() { return true; } //...until here!
}
fooCheck();
Saya tidak dapat menemukan referensi tunggal mengapa itu harus bekerja. Saya pertama kali melihat ini dalam catatan presentasi John Resig, tetapi hanya disebutkan. Tidak ada penjelasan di sana atau di mana pun dalam hal ini.
Bisakah seseorang tolong beri saya pencerahan?
javascript
function
Edu Felipe
sumber
sumber
Jawaban:
The
function
deklarasi sihir dan menyebabkan identifier untuk terikat sebelum sesuatu dalam kode-blok yang * dijalankan.Ini berbeda dari tugas dengan
function
ekspresi, yang dievaluasi dalam urutan top-down normal.Jika Anda mengubah contoh untuk mengatakan:
itu akan berhenti bekerja.
Deklarasi fungsi secara sintaksis cukup terpisah dari ekspresi fungsi, meskipun mereka terlihat hampir identik dan dapat ambigu dalam beberapa kasus.
Ini didokumentasikan dalam standar ECMAScript , bagian 10.1.3 . Sayangnya ECMA-262 bukan dokumen yang sangat mudah dibaca bahkan oleh standar-standar!
*: fungsi, blok, modul atau skrip yang berisi.
sumber
Ini disebut HOISTING - Memanggil (memanggil) fungsi sebelum didefinisikan.
Dua jenis fungsi yang ingin saya tulis adalah:
Fungsi Ekspresi & Fungsi Deklarasi
Fungsi ekspresi:
Ekspresi fungsi dapat disimpan dalam variabel sehingga tidak perlu nama fungsi. Mereka juga akan dinamai sebagai fungsi anonim (fungsi tanpa nama).
Untuk memanggil (memanggil) fungsi-fungsi ini, mereka selalu membutuhkan nama variabel . Fungsi semacam ini tidak akan berfungsi jika dipanggil sebelum didefinisikan yang berarti Pengangkatan tidak terjadi di sini. Kita harus selalu mendefinisikan fungsi ekspresi terlebih dahulu dan memohonnya.
Ini adalah bagaimana Anda dapat menulisnya dalam ECMAScript 6:
Fungsi Deklarasi:
Fungsi yang dideklarasikan dengan sintaks berikut tidak dieksekusi segera. Mereka "disimpan untuk digunakan nanti" dan akan dieksekusi nanti, ketika mereka dipanggil (dipanggil). Jenis fungsi ini berfungsi jika Anda menyebutnya SEBELUM atau SETELAH di tempat yang telah ditentukan. Jika Anda memanggil fungsi deklarasi sebelum didefinisikan, mengangkat berfungsi dengan benar.
Mengangkat contoh:
sumber
let fun = theFunction; fun(); function theFunction() {}
juga akan berfungsi (Node dan browser)Peramban membaca HTML Anda dari awal hingga akhir dan dapat menjalankannya saat dibaca dan diuraikan menjadi potongan yang dapat dieksekusi (deklarasi variabel, definisi fungsi, dll.) Tetapi pada titik mana pun hanya dapat menggunakan apa yang telah didefinisikan dalam skrip sebelum titik itu.
Ini berbeda dari konteks pemrograman lain yang memproses (kompilasi) semua kode sumber Anda, mungkin menautkannya bersama-sama dengan perpustakaan yang Anda butuhkan untuk menyelesaikan referensi, dan membangun modul yang dapat dieksekusi, di mana titik eksekusi dimulai.
Kode Anda dapat merujuk ke objek bernama (variabel, fungsi lain, dll.) Yang didefinisikan lebih jauh, tetapi Anda tidak dapat menjalankan kode rujukan sampai semua bagian tersedia.
Ketika Anda terbiasa dengan JavaScript, Anda akan sangat menyadari kebutuhan Anda untuk menulis sesuatu dalam urutan yang tepat.
Revisi: Untuk mengonfirmasi jawaban yang diterima (di atas), gunakan Firebug untuk melangkah ke bagian skrip halaman web. Anda akan melihatnya melompat dari fungsi ke fungsi, hanya mengunjungi baris pertama, sebelum benar-benar mengeksekusi kode apa pun.
sumber
Beberapa bahasa memiliki persyaratan bahwa pengidentifikasi harus didefinisikan sebelum digunakan. Alasan untuk ini adalah bahwa kompiler menggunakan pass tunggal pada kode sumber.
Tetapi jika ada beberapa pass (atau beberapa cek ditunda) Anda dapat hidup sempurna tanpa persyaratan itu. Dalam hal ini, kode mungkin pertama kali dibaca (dan ditafsirkan) dan kemudian tautannya diatur.
sumber
Saya hanya menggunakan JavaScript sedikit. Saya tidak yakin apakah ini akan membantu, tetapi terlihat sangat mirip dengan apa yang Anda bicarakan dan mungkin memberikan wawasan:
http://www.dustindiaz.com/javascript-function-declaration-ambiguity/
sumber
Badan fungsi "internalFoo" perlu pergi ke suatu tempat pada waktu parsing, jadi ketika kode dibaca (alias parsing) oleh JS interpreter, struktur data untuk fungsi tersebut dibuat dan namanya ditetapkan.
Baru kemudian, kemudian kode dijalankan, JavaScript benar-benar mencoba mencari tahu apakah "internalFoo" ada dan apa itu dan apakah itu bisa dipanggil, dll.
sumber
Untuk alasan yang sama, yang berikut ini akan selalu dimasukkan ke
foo
dalam namespace global:sumber
if
blok tidak membuat ruang lingkup, sementarafunction()
blok selalu menciptakan satu. Alasan sebenarnya adalah bahwa definisi nama javascript global terjadi pada fase kompilasi, sehingga bahkan jika kode tidak berjalan, nama tersebut didefinisikan. (Maaf butuh waktu lama untuk berkomentar)