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()
ซึ่งทำให้เกิดข้อผิดพลาด