Hoisting trong JavaScript

Tạo bởi Hoàng Vũ, chỉnh sửa cuối lúc 10 tháng 3, 2025

Hoisting là một cơ chế đặc biệt trong JavaScript, giúp "nâng" phần khai báo biến và hàm lên đầu phạm vi của chúng trước khi thực thi code.

Trong bài này, bạn sẽ học về:

  • Hoisting là gì?
  • Cách hoisting hoạt động với var, let, const.
  • Hoisting trong function declarationfunction expression.
  • Tác động của hoisting đến code và cách tránh lỗi.
  • Ví dụ thực tế về hoisting.

Hoisting trong JavaScript

1. Hoisting là gì?**

Hoisting là cơ chế đưa phần khai báo biến và hàm lên đầu phạm vi chứa chúng trước khi code chạy.

Ví dụ:

console.log(name); // Điều gì sẽ xảy ra?
var name = "JavaScript";

Kết quả:

undefined

Giải thích:

  • JavaScript nâng (hoist) phần khai báo var name lên đầu, nhưng không nâng giá trị gán ("JavaScript") lên.
  • Do đó, name tồn tại nhưng chưa có giá trị → undefined.

Tương đương với:

var name;
console.log(name); // undefined
name = "JavaScript";

2. Hoisting với var, let, const

var – Bị hoisting nhưng không có giá trị

console.log(a); // undefined
var a = 10;
console.log(a); // 10

Giải thích:

  • var a được hoisting lên đầu với giá trị mặc định undefined.

Tương đương với:

var a;
console.log(a); // undefined
a = 10;
console.log(a); // 10

let & const – Bị hoisting nhưng không thể sử dụng trước khi khai báo.

console.log(b); // Lỗi: Cannot access 'b' before initialization
let b = 20;

Giải thích:

  • b vẫn bị hoisting lên đầu, nhưng không được gán giá trị mặc định undefined.
  • Nếu truy cập trước khi khai báo, sẽ bị lỗi (trong "Temporal Dead Zone" - TDZ).

Tương tự với const:

console.log(c); // Lỗi
const c = 30;

Tóm tắt:

Loại biến Bị hoisting? Giá trị mặc định khi hoisting? Có thể dùng trước khi khai báo?
var undefined Được, nhưng nhận undefined
let Không có giá trị Lỗi nếu dùng trước khai báo
const Không có giá trị Lỗi nếu dùng trước khai báo

3. Hoisting trong function declaration và function expression

Function Declaration – Được hoisting hoàn toàn

greet(); // Chạy bình thường

function greet() {
    console.log("Hello JavaScript!");
}

Giải thích:

  • Toàn bộ function greet() được hoisting lên đầu, nên có thể gọi trước khai báo.

Tương đương với:

function greet() {
    console.log("Hello JavaScript!");
}

greet();

Function Expression – Không được hoisting hoàn toàn

hello(); // Lỗi: Cannot access 'hello' before initialization

const hello = function() {
    console.log("Hello!");
};

Giải thích:

  • Chỉ phần khai báo hello được hoisting, nhưng không nâng phần gán hàm.
  • hello nằm trong Temporal Dead Zone (TDZ), nên không thể gọi trước khi khai báo.

4. Tác động của hoisting đến code

Cẩn thận với var vì dễ gây lỗi!
Ví dụ sai lầm phổ biến:

console.log(count); // undefined
if (true) {
    var count = 5;
}
console.log(count); // 5

Lý do:

  • var count bị hoisting lên đầu, nhưng chưa có giá trị ban đầu.
  • Khi chạy, count tồn tại toàn cục, gây lỗi khó phát hiện.

Ví dụ thực tế về hoisting

Ví dụ 1: Hoisting trong vòng lặp (Sự khác biệt giữa varlet)

for (var i = 0; i < 3; i++) {
    setTimeout(() => console.log(i), 1000);
}

Output sau 1 giây:

3
3
3

Lý do:

  • var i bị hoisting và có phạm vi toàn cục, nên sau vòng lặp, i = 3.
  • Khi setTimeout chạy, i đã là 3.

Sửa lại với let:

for (let i = 0; i < 3; i++) {
    setTimeout(() => console.log(i), 1000);
}

Output đúng mong muốn:

0
1
2

let có phạm vi khối (block scope), mỗi lần lặp tạo một i mới.

Ví dụ 2: Tránh lỗi hoisting với const

Sai lầm phổ biến:

console.log(username); // Lỗi: Cannot access 'username' before initialization
const username = "John";

Cách đúng:

const username = "John";
console.log(username); // Output: John

Kết luận

  • Hoisting nâng khai báo lên đầu, nhưng không nâng giá trị gán.
  • var bị hoisting nhưng nhận giá trị undefined, dễ gây lỗi.
  • let & const cũng bị hoisting nhưng không thể dùng trước khai báo (TDZ).
  • function declaration được hoisting đầy đủ, nhưng function expression không.
  • Luôn khai báo biến và hàm trước khi sử dụng để tránh lỗi hoisting.
Website Logo

Với hơn 10 năm kinh nghiệm lập trình web và từng làm việc với nhiều framework, ngôn ngữ như PHP, JavaScript, React, jQuery, CSS, HTML, CakePHP, Laravel..., tôi hy vọng những kiến thức được chia sẻ tại đây sẽ hữu ích và thiết thực cho các bạn.

Bình luận

Website Logo

Chào, tôi là Vũ. Đây là blog hướng dẫn lập trình của tôi.

Liên hệ công việc qua email dưới đây.

lhvuctu@gmail.com

Chúng Tôi Trên

Bạn đang muốn học về lập trình website?

Bạn cần nâng cao kiến thức chuyên nghiệp hơn để nâng cao cơ hội nghề nghiệp? Liên hệ