tl; drถ้าคุณไม่ได้โทรหาอะไรเลยจนกว่าทุกอย่างจะโหลดเสร็จคุณก็สบายดี
แก้ไข: สำหรับภาพรวมซึ่งครอบคลุมการประกาศ ES6 ( let, const): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet
พฤติกรรมแปลก ๆ นี้ขึ้นอยู่กับ
- คุณกำหนดฟังก์ชันและ
- เมื่อคุณโทรหาพวกเขา
นี่คือตัวอย่างบางส่วน
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();
นี่เป็นเพราะสิ่งที่เรียกว่าการชักรอก !
ฟังก์ชั่น: มีสองวิธีที่จะกำหนดฟังก์ชั่นที่มีการประกาศและฟังก์ชั่นการแสดงออก ความแตกต่างนั้นน่ารำคาญและเป็นนาทีดังนั้นสมมติว่าสิ่งนี้ผิดเล็กน้อย: หากคุณกำลังเขียนมันเหมือนfunction name() {}เป็นการประกาศและเมื่อคุณเขียนมันเช่นvar name = function() {}(หรือฟังก์ชันที่ไม่ระบุตัวตนที่กำหนดให้ส่งคืนสิ่งต่างๆเช่นนั้น) ฟังก์ชั่นการแสดงออก
ก่อนอื่นมาดูวิธีจัดการตัวแปร:
var foo = 42;
//the interpreter turns it into this:
var foo;
foo = 42;
ตอนนี้วิธีจัดการการประกาศฟังก์ชัน:
var foo = 42;
function bar() {}
//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;
varงบ "โยน" การสร้างของfooไปด้านบนมาก แต่ไม่ได้กำหนดค่าให้มันยัง fooการประกาศฟังก์ชั่นมาในบรรทัดถัดไปและในที่สุดก็มีค่าได้รับมอบหมายให้
แล้วนี่ล่ะ?
bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;
เฉพาะประกาศของfooถูกย้ายไปด้านบน การมอบหมายจะเกิดขึ้นหลังจากมีการโทรหาbarเท่านั้นซึ่งเป็นจุดเริ่มต้นก่อนที่จะเกิดการชักรอกทั้งหมด
และสุดท้ายเพื่อความกระชับ:
bar();
function bar() {}
//turns to
function bar() {}
bar();
แล้วนิพจน์ฟังก์ชันล่ะ
var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();
เช่นเดียวกับตัวแปรทั่วไปอันดับแรกfooจะถูกประกาศที่จุดสูงสุดของขอบเขตจากนั้นจึงกำหนดค่า
มาดูกันว่าเหตุใดตัวอย่างที่สองจึงเกิดข้อผิดพลาด
bar();
function bar() {
foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
foo();
}
bar();
foo = function() {}
ดังที่เราเคยเห็นมาก่อนมีเพียงการสร้างเท่านั้นที่fooถูกยกขึ้นงานจะมาในตำแหน่งที่ปรากฏในรหัส "ดั้งเดิม" (ไม่ได้รับการยก) เมื่อbarจะเรียกว่ามันเป็นก่อนที่จะมีการกำหนดค่าเพื่อให้foo foo === undefinedตอนนี้ใน function-body ของbarมันเหมือนกับว่าคุณกำลังทำอยู่undefined()ซึ่งทำให้เกิดข้อผิดพลาด