ฉันได้ยินมาว่าการเข้าถึงlet
และconst
ค่านิยมก่อนที่จะเริ่มต้นสามารถทำให้เกิดReferenceError
เพราะสิ่งที่เรียกว่าเขตตายชั่วคราวเขตตายชั่วคราว
โซนตายชั่วคราวคืออะไรมันเกี่ยวข้องกับขอบเขตและการชักรอกอย่างไรและในสถานการณ์ใดที่พบ
ฉันได้ยินมาว่าการเข้าถึงlet
และconst
ค่านิยมก่อนที่จะเริ่มต้นสามารถทำให้เกิดReferenceError
เพราะสิ่งที่เรียกว่าเขตตายชั่วคราวเขตตายชั่วคราว
โซนตายชั่วคราวคืออะไรมันเกี่ยวข้องกับขอบเขตและการชักรอกอย่างไรและในสถานการณ์ใดที่พบ
คำตอบ:
let
และconst
มีความแตกต่างสองประการจากvar
:
var
ก่อนที่จะมีการประกาศมีผลundefined
; การเข้าถึง a let
หรือconst
ก่อนที่จะมีการประกาศพ่นReferenceError
:console.log(aVar); // undefined
console.log(aLet); // causes ReferenceError: aLet is not defined
var aVar = 1;
let aLet = 2;
ปรากฏขึ้นจากตัวอย่างเหล่านี้ว่าlet
การประกาศ (และใช้const
งานในลักษณะเดียวกัน) อาจไม่ถูกยกขึ้นเนื่องจากaLet
ไม่ปรากฏว่ามีอยู่ก่อนที่จะถูกกำหนดค่า
นั่นคือไม่ได้กรณีที่ however- let
และconst
ได้รับการยก (เช่นvar
, class
และfunction
) แต่มีช่วงเวลาระหว่างการป้อนขอบเขตและการประกาศที่พวกเขาไม่สามารถเข้าถึง ช่วงเวลานี้เป็นเขตตายชั่วคราว (TDZ)
TDZ สิ้นสุดลงเมื่อaLet
มีการประกาศมากกว่าที่ได้รับมอบหมาย :
//console.log(aLet) // would throw ReferenceError
let aLet;
console.log(aLet); // undefined
aLet = 10;
console.log(aLet); // 10
ตัวอย่างนี้แสดงให้เห็นว่าlet
มีการยก:
let x = 'outer value';
(function() {
// start TDZ for x
console.log(x);
let x = 'inner value'; // declaration ends TDZ for x
}());
เครดิต: Temporal Dead Zone (TDZ) demystified
การเข้าถึงในขอบเขตด้านในยังคงทำให้เกิดx
ReferenceError
หากlet
ไม่ถูกชักรอกมันจะเข้าสู่ระบบouter value
ไม่ได้ถูกยกขึ้นก็จะเข้าสู่ระบบ
TDZ เป็นสิ่งที่ดีเพราะมันช่วยเน้นข้อบกพร่อง - การเข้าถึงค่าก่อนที่จะถูกประกาศนั้นไม่ค่อยมีเจตนา
TDZ ยังใช้กับอาร์กิวเมนต์ฟังก์ชันที่เป็นค่าเริ่มต้น อาร์กิวเมนต์จะถูกประเมินจากซ้ายไปขวาและแต่ละอาร์กิวเมนต์อยู่ใน TDZ จนกว่าจะมีการกำหนด:
// b is in TDZ until its value is assigned
function testDefaults(a=b, b) { }
testDefaults(undefined, 1); // throws ReferenceError because the evaluation of a reads b before it has been evaluated.
TDZ ไม่ได้เปิดใช้งานโดยค่าเริ่มต้นในbabel.js transpiler เปิดโหมด "การปฏิบัติที่สูง" ที่จะใช้มันในREPL จัดหาes6.spec.blockScoping
แฟล็กเพื่อใช้กับ CLI หรือเป็นไลบรารี
แนะนำอ่านเพิ่มเติม: TDZ demystifiedและES6 อนุญาต, Const และ“ชั่วตายโซน” (TDZ) ในความลึก
let foo
ในบล็อกทำให้ยกขึ้นและประกาศที่ด้านบนของบล็อกนั้น สายของlet foo
สาเหตุที่จะเริ่มต้น และfoo = xyz
ทำให้มันถูกกำหนดค่า
การชักรอก:
let
, const
, var
ทุกคนได้รับการยกกระบวนการ
(หมายถึงอะไรพวกเขาไปด้านบนและประกาศที่ด้านบนของขอบเขต)
initialisation:
var
ผ่านไปยังกระบวนการเริ่มต้นและรับค่าเริ่มต้นเป็น undefined
เป็นlet
, const
ไม่ได้ไปโยนกระบวนการเริ่มต้นดังนั้นค่าของพวกเขายังคงไม่สามารถเข้าถึงได้แม้ว่าพวกเขาประกาศแล้ว อะไรใส่ไว้ในtemporal dead zone
ดังนั้นในไม่ช้า:
กระบวนการ hoisting:
var
,let
,const
กระบวนการ initialisation:var
ในกรณีของตัวแปร let และ const โดยทั่วไป Temporal Dead Zone เป็นโซน
"ก่อนที่จะประกาศตัวแปรของคุณ",
เช่นที่คุณไม่สามารถเข้าถึงค่าของตัวแปรเหล่านี้มันจะโยนข้อผิดพลาด
อดีต
let sum = a + 5; //---------
//some other code // | ------> this is TDZ for variable a
// |
console.log(sum) //---------
let a = 5;
รหัสด้านบนให้ข้อผิดพลาด
รหัสเดียวกันจะไม่ให้ข้อผิดพลาดเมื่อเราใช้ var สำหรับตัวแปร 'a'
อดีต
var sum = a;
console.log(sum) //prints undefined
var a = 5;
undefined
และ5
) การประกาศของvar a
ยกขึ้นรหัส inifialisation ที่ส่งa
ถึง 5 นั้นไม่ใช่