Tôi từng nghe nhiều người nói: "JavaScript hoists (kéo lên) các biến và hàm", và thật lòng mà nói… điều đó chỉ khiến tôi rối thêm.
Nhưng một khi tôi thấy nó hoạt động thực tế, thì mọi thứ mới thực sự sáng tỏ.
Trong bài viết này, tôi sẽ giải thích hoisting thực sự là gì, nó hoạt động như thế nào phía sau hậu trường, và cách nó có thể khiến bạn "vấp ngã" trong các buổi phỏng vấn.
Hoisting là gì?
Hoisting là cách JavaScript đọc code của bạn trước khi nó thực sự thực thi.
Ngay khi chương trình bắt đầu, JavaScript sẽ quét nhanh toàn bộ mã nguồn và dành sẵn không gian bộ nhớ cho tất cả các biến và hàm mà bạn đã khai báo.
- Với các biến được khai báo bằng
var
, JavaScript gán cho chúng giá trịundefined
. - Với các hàm được khai báo bằng từ khóa function, toàn bộ phần thân hàm sẽ được lưu trữ, vì vậy bạn có thể gọi hàm đó trước cả khi nó được viết trong mã nguồn.
Quá trình thiết lập ngầm này được gọi là hoisting.
Ví dụ minh họa
Ví dụ 1: Hoisting với var
console.log(name); var name = "John";
Kết quả:
undefined
JavaScript thực chất hiểu đoạn mã như sau:
var name;
console.log(name); // undefined
name = "John";
Ví dụ 2: Sử dụng biến chưa được khai báo
console.log(age); var name = "John";
Kết quả:
ReferenceError: age is not defined
Tại sao? Vì age
chưa từng được khai báo, nên không có vùng nhớ nào được cấp cho nó trong quá trình quét ban đầu.
Ví dụ 3: Hàm khai báo được hoisting hoàn toàn
sayHello(); function sayHello() { console.log("Hello!");
}
Kết quả:
Hello!
Toàn bộ hàm được hoisting lên đầu.
Ví dụ 4: Arrow function không được hoisting
greet(); // ❌ TypeError: greet is not a function var greet = () => { console.log("Hi there!");
};
Mặc dù greet
được khai báo bằng var
, nhưng arrow function hoạt động giống như biến, không như một hàm được hoisting
Ghi chú: let
và const
không giống var
console.log(age); // ❌ ReferenceError let age = 25;
Tại sao vẫn lỗi dù đã khai báo age
?
Đó là vì một khái niệm gọi là "Temporal Dead Zone (TDZ)" – vùng chết tạm thời.
“Ừ, tôi biết age tồn tại, nhưng bạn không thể chạm vào nó cho đến khi tôi thực sự đến dòng khai báo.”
Vì vậy, không giống như var
, JavaScript không gán giá trị undefined
tạm thời cho let
và const
. Bạn sẽ gặp lỗi ReferenceError
nếu cố gắng truy cập chúng quá sớm.
Hy vọng qua bài viết này các bạn đã hiểu rõ được khái niệm Hoisting trong JavaScript là gì.