Tôi đã từng nghĩ rằng việc cẩu chỉ xảy ra với các biến được khai báo bằng var
. Nhưng gần đây, tôi biết được rằng nó cũng xảy ra với các biến được khai báo bằng let
và const
.
Tôi sẽ giải thích những gì tôi muốn nói trong bài viết này.
Tôi cũng có một phiên bản video của bài viết này, bạn có thể xem nếu bạn quan tâm.
Làm thế nào Palăng hoạt động với var
trong JavaScript
Đây là cách cẩu hoạt động trên các biến được khai báo với var
:
console.log(number)
// undefined
var number = 10
console.log(number)
// 10
Các number
biến được nâng lên đầu phạm vi toàn cầu. Điều này giúp có thể truy cập biến trước dòng nó được khai báo mà không gặp lỗi.
Nhưng những gì bạn sẽ nhận thấy ở đây là chỉ khai báo biến (var number
) được nâng lên – phần khởi tạo (= 10
) không phải. Vì vậy, khi bạn cố gắng truy cập number
trước khi nó được khai báo, bạn nhận được khởi tạo mặc định xảy ra với var đó là undefined
.
Sau đó, dòng khai báo và khởi tạo được thực hiện, vì vậy việc truy cập number
sau đó trả về giá trị khởi tạo, 10.
Cách cẩu hoạt động với let/const trong JavaScript
Nếu bạn cố gắng làm điều tương tự như trên với let
hoặc const
đây là những gì xảy ra:
console.log(number)
let number = 10
// or const number = 10
console.log(number)
Bạn nhận được một lỗi cho biết: ReferenceError: Không thể truy cập ‘số’ trước khi khởi tạo.
Vì vậy, bạn có thể truy cập một biến được khai báo bằng var trước khi khai báo mà không gặp lỗi, nhưng bạn không thể làm điều tương tự với let
hoặc const
.
Đây là lý do tại sao tôi luôn nghĩ rằng cẩu chỉ xảy ra với var, nó không xảy ra với let hoặc const.
Nhưng như tôi đã nói, gần đây tôi đã biết rằng các biến được khai báo bằng let
hoặc const
cũng được cẩu lên. Hãy để tôi giải thích.
Hãy xem ví dụ này:
console.log(number2)
let number = 10
Tôi đăng nhập một biến gọi là number2
vào bàn điều khiển, tôi khai báo và khởi tạo một biến có tên là number
.
Chạy mã này tạo ra lỗi này: ReferenceError: number2 không được xác định
Bạn nhận thấy gì giữa lỗi trước và lỗi này? Lỗi trước đó nói ReferenceError: Không thể truy cập ‘số’ trước khi khởi tạo trong khi lỗi mới này nói ReferenceError: number2 không được xác định.
Đây là sự khác biệt. Cái trước nói “không thể truy cập trước khi khởi tạo” trong khi cái sau nói “không được xác định”.
Điều sau có nghĩa là JavaScript không biết gì number2
biến là do nó không được định nghĩa – và thực sự là chúng ta không định nghĩa nó. Chúng tôi chỉ xác định number
.
Nhưng cái trước không nói “không được xác định”, thay vào đó, nó nói, “không thể truy cập trước khi khởi tạo”. Đây là mã một lần nữa:
console.log(number)
// ReferenceError: Cannot access 'number' before initialization
let number = 10
console.log(number)
Điều này có nghĩa là JavaScript “biết” về number
Biến đổi. Làm sao nó biết được? Bởi vì number
được nâng lên trên cùng của phạm vi toàn cầu.
Nhưng tại sao lại xảy ra lỗi? Chà, điều này làm rõ sự khác biệt giữa hành vi cẩu với var
và let
/const
.
Các biến được khai báo với let
hoặc const
là được nâng lên KHÔNG CÓ khởi tạo mặc định. Vì vậy, việc truy cập chúng trước dòng chúng được tuyên bố ném ReferenceError: Không thể truy cập ‘biến’ trước khi khởi tạo.
Nhưng các biến được khai báo với var
là được nâng lên VỚI khởi tạo mặc định là không xác định. Vì vậy, truy cập chúng trước dòng chúng được khai báo trả về undefined
.
Vùng chết tạm thời
Có một tên cho khoảng thời gian trong quá trình thực hiện nơi let
/const
các biến được nâng lên nhưng không thể truy cập được: nó được gọi là Vùng chết tạm thời.
Một lần nữa, mã từ trên:
console.log(number)
let number = 10
console.log(number)
Các number
biến nằm trong vùng chết tạm thời nơi JavaScript biết về sự tồn tại của nó (vì khai báo của nó được nâng lên) nhưng không thể truy cập được (vì nó không có phần khởi tạo).
kết thúc
Nếu bạn giống tôi và bạn nghĩ rằng cẩu chỉ áp dụng với var
và không let
/const
Tôi hy vọng bài viết này làm sáng tỏ giả định sai lầm đó.
Như tôi đã giải thích trong bài viết này, let
và const
các biến được nâng lên, chỉ chúng được nâng lên mà không có khởi tạo mặc định. Điều này khiến chúng không thể truy cập được (vì các biến như vậy nằm trong vùng chết tạm thời).
Các biến được khai báo với var
mặt khác, được nâng lên với khởi tạo mặc định là undefined
.
Tôi hy vọng bạn đã học được điều gì đó từ bài viết này 🙂