Vùng chết tạm thời là gì?


150

Tôi đã nghe nói rằng việc truy cập letconstcác giá trị trước khi chúng được khởi tạo có thể gây ra một ReferenceErrorthứ gọi là vùng chết tạm thời .

Vùng chết tạm thời là gì, nó liên quan đến phạm vi và cẩu như thế nào, và trong những tình huống nào nó gặp phải?


6
có thể trùng lặp các biến được khai báo với let hoặc const không được nâng lên trong ES6 không? - mặc dù câu hỏi không tập trung vào TDZ, nhưng các câu trả lời về cơ bản là giống nhau
Bergi

Câu trả lời:


201

letconstcó hai điểm khác biệt lớn từ var:

  1. Họ là khối phạm vi .
  2. Truy cập vartrước khi nó được tuyên bố có kết quả undefined; truy cập một lethoặc consttrước khi nó được tuyên bố ném ReferenceError:

console.log(aVar); // undefined
console.log(aLet); // causes ReferenceError: aLet is not defined
var aVar = 1;
let aLet = 2;

Nó xuất hiện từ các ví dụ này rằng các letkhai báo (và const, hoạt động theo cùng một cách) có thể không được nâng lên , vì aLetdường như không tồn tại trước khi nó được gán một giá trị.

Tuy nhiên, đó không phải là trường hợp letconst được nâng lên (như var, classfunction), nhưng có một khoảng thời gian giữa việc nhập phạm vi và được khai báo ở nơi không thể truy cập được. Thời kỳ này là vùng chết tạm thời (TDZ) .

TDZ kết thúc khi aLetđược khai báo , thay vì được chỉ định :

//console.log(aLet)  // would throw ReferenceError

let aLet;
console.log(aLet); // undefined
aLet = 10;
console.log(aLet); // 10

Ví dụ này cho thấy letđược nâng lên:

let x = 'outer value';
(function() {
  // start TDZ for x
  console.log(x);
  let x = 'inner value'; // declaration ends TDZ for x
}());

Tín dụng: Khu vực chết tạm thời (TDZ) bị phá hủy

Truy cập xtrong phạm vi bên trong vẫn gây ra a ReferenceError. Nếu letkhông được nâng lên, nó sẽ đăng nhập outer value.

TDZ là một điều tốt vì nó giúp làm nổi bật các lỗi mà truy cập vào một giá trị trước khi nó được tuyên bố là hiếm khi có chủ ý.

TDZ cũng áp dụng cho các đối số chức năng mặc định. Các đối số được đánh giá từ trái sang phải và mỗi đối số nằm trong TDZ cho đến khi được chỉ định:

// 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 không được bật theo mặc định trong trình chuyển mã babel.js. Bật chế độ "tuân thủ cao" để sử dụng nó trong REPL . Cung cấp es6.spec.blockScopingcờ để sử dụng nó với CLI hoặc làm thư viện.

Đề nghị đọc thêm: TDZ đã được làm sáng tỏES6 Let, Const và khu vực tạm thời tạm thời (TDZ) ở độ sâu .



@zeroflagL liên kết tốt, cảm ơn. Ngoài ra, nó nói: "foo không được khai báo, nó chưa được khởi tạo", ngôn ngữ đó sẽ hữu ích để làm rõ / chính xác trong câu trả lời ở trên. let footrong một khối làm cho nó được nâng lên và khai báo ở đầu khối đó. Dòng let foonguyên nhân nó được khởi tạo. Và foo = xyzlàm cho nó được gán một giá trị.
AJP

2
Tôi nghĩ rằng đây là một bài tuyệt vời! Tuy nhiên, tôi có ấn tượng rằng 'chúng ta' không phải là người nâng hàng? Tôi đã tìm thấy điều này trong các tài liệu Mozilla: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ trộm Tôi không cố gắng trở thành một người tò mò, tôi chỉ tò mò và được mở để làm rõ.
dmarges

1
@jeows Trang MDN vẫn cho biết họ không được nâng lên. Bạn nên cố gắng chỉnh sửa điều đó, nếu bạn thực sự chắc chắn về những gì bạn đang nói. Tôi nghĩ rằng tôi nên đăng một câu hỏi về điều đó.
doubleOrt

1
@joews IMO, bạn có thể nói rằng họ đã được nâng lên nhưng họ không thể truy cập được trước khi đạt được tuyên bố của họ vì TDZ hoặc bạn có thể nói rằng họ không được nâng lên nhưng TDZ sẽ khiến bất kỳ tài liệu tham khảo nào về họ đưa ra lỗi. Thực tế, cả hai tuyên bố đều đúng như nhau. Ngoại trừ, tôi nghĩ rằng, bạn đang sử dụng thuật ngữ "cẩu" theo nghĩa trừu tượng, như trong "cẩu = bất cứ khi nào động cơ nhận thức được sự tồn tại của biến đó". Có phải vậy không? Thêm vào đó, thông số kỹ thuật nói gì về điều đó?
doubleOrt

7

Cẩu:
let , const, varđều get quá trình kéo lên.
(những gì có nghĩa là họ đi lên trên và tuyên bố ở trên cùng của phạm vi.)

Khởi tạo:

  • varcũng trải qua quá trình ban đầu và nhận giá trị ban đầu của undefined.
  • trong khi đó let, constđã không thực hiện quy trình ban đầu, vì vậy giá trị của chúng vẫn không thể truy cập được, mặc dù chúng đã được khai báo. những gì đặt chúng vàotemporal dead zone

Vì vậy, trong thời gian ngắn:

quá trình cẩu: var, let, const
quá trình initialisation: var


0

Trong trường hợp biến let và const, về cơ bản, Vùng chết tạm thời là một vùng

"trước khi biến của bạn được khai báo",

tức là khi bạn không thể truy cập giá trị của các biến này, nó sẽ đưa ra lỗi.

Ví dụ.

let sum = a + 5;        //---------
//some other code       //         | ------>  this is TDZ for variable a
                        //         |
console.log(sum)        //---------
let a = 5;

đoạn mã trên có lỗi

cùng một mã sẽ không gây ra lỗi khi chúng ta sử dụng var cho biến 'a',

Ví dụ.

var sum = a;                            
console.log(sum)     //prints undefined
var a = 5;

nhật ký giao diện điều khiển tạo ra "NaN" trong ví dụ thứ hai (kết quả của việc thêm undefined5). Các declaratation của var ađược kéo lên, mã inifialisation settng ađến 5 thì không.
traktor53

vâng, đúng, a được nâng lên mà không có bất kỳ sự khởi tạo nào. Vì vậy, một sẽ không được xác định.
niranjan harpale

Ví dụ đầu tiên được trích dẫn là không đúng, xin vui lòng sửa nó hoặc loại bỏ nó.
Web của Spidi ngày
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.