tl; dr Jika Anda tidak menelepon apa pun sampai semuanya dimuat, Anda akan baik-baik saja.
Edit: Untuk gambaran umum yang juga mencakup beberapa deklarasi ES6 ( let, const): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
Perilaku aneh ini bergantung pada
- Bagaimana Anda mendefinisikan fungsi dan
- Saat Anda menelepon mereka.
Berikut beberapa contohnya.
bar(); //This won't throw an error
function bar() {}
foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
foo(); //no error
}
var foo = function() {}
bar();
Ini karena sesuatu yang disebut mengangkat !
Ada dua cara untuk mendefinisikan fungsi: Deklarasi fungsi dan ekspresi fungsi . Perbedaannya menjengkelkan dan menit, jadi anggap saja hal ini sedikit salah: Jika Anda menulisnya seperti function name() {}, itu adalah deklarasi , dan ketika Anda menulisnya seperti var name = function() {}(atau fungsi anonim yang ditugaskan untuk mengembalikan, hal-hal seperti itu), itu ekspresi fungsi .
Pertama, mari kita lihat bagaimana variabel ditangani:
var foo = 42;
//the interpreter turns it into this:
var foo;
foo = 42;
Sekarang, bagaimana deklarasi fungsi ditangani:
var foo = 42;
function bar() {}
//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;
The varpernyataan "melempar" yang penciptaan dari fooke puncak, tetapi tidak menetapkan nilai untuk itu belum. Deklarasi fungsi muncul di baris berikutnya, dan akhirnya sebuah nilai ditetapkan ke foo.
Dan bagaimana dengan ini?
bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;
Hanya deklarasi dari foodipindahkan ke atas. Penugasan dilakukan hanya setelah panggilan ke bardilakukan, di mana sebelum semua pengangkatan terjadi.
Dan akhirnya, untuk ringkasnya:
bar();
function bar() {}
//turns to
function bar() {}
bar();
Sekarang, bagaimana dengan ekspresi fungsi ?
var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();
Sama seperti variabel biasa, pertama fooadalah dideklarasikan pada titik tertinggi dari ruang lingkup, maka ditugaskan nilai.
Mari kita lihat mengapa contoh kedua memunculkan kesalahan.
bar();
function bar() {
foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
foo();
}
bar();
foo = function() {}
Seperti yang telah kita lihat sebelumnya, hanya pembuatan dari fooyang diangkat, tugas datang di tempat ia muncul di kode "asli" (tidak dikerek). Ketika bardipanggil, itu sebelum foodiberi nilai, jadi foo === undefined. Sekarang di dalam function-body dari bar, seolah-olah Anda sedang melakukan undefined(), yang membuat kesalahan.