Chào các bạn, những người đam mê lập trình! Trong thế giới JavaScript năng động, việc quản lý biến số là một kỹ năng cơ bản nhưng cực kỳ quan trọng. Từng có thời, var là "ông hoàng" duy nhất. Nhưng rồi, let và const xuất hiện, mang đến một cuộc cách mạng thực sự. Vậy ba "người anh em" này khác nhau thế nào và khi nào nên dùng ai? Hãy cùng tôi tìm hiểu nhé!
Var: Người Anh Cả "Dễ Dãi" (và đôi khi rắc rối)
- Phạm vi (Scope):
varcó phạm vi hàm (function scope). Điều này có nghĩa là biến được khai báo vớivarchỉ có thể truy cập được trong hàm mà nó được định nghĩa, hoặc toàn cục nếu khai báo bên ngoài mọi hàm. - Hoisting: Biến khai báo với
varđược hoisting lên đầu phạm vi của nó. Tức là bạn có thể truy cập biến trước khi nó được khai báo, nhưng giá trị ban đầu sẽ làundefined. - Khai báo lại & Gán lại: Bạn có thể khai báo lại và gán lại giá trị cho biến
vartrong cùng một phạm vi mà không gặp lỗi.
console.log(a); // undefined (hoisted)var a = 10;console.log(a); // 10function exampleVar() { var x = 5; if (true) { var x = 10; // Khai báo lại, không phải biến mới console.log(x); // 10 } console.log(x); // 10 (x vẫn là 10 do function scope)}exampleVar();var b = 1;var b = 2; // Khai báo lại hợp lệconsole.log(b); // 2Vấn đề của var: Do phạm vi hàm và khả năng khai báo lại, var dễ gây ra lỗi khó debug, đặc biệt trong các vòng lặp hoặc khối lệnh if/else.
Let: Kỷ Nguyên Mới của Phạm Vi Khối (Block Scope)
- Phạm vi (Scope):
letcó phạm vi khối (block scope). Tức là biến chỉ tồn tại trong khối lệnh ({}) mà nó được định nghĩa, bao gồm cả vòng lặp và điều kiện. - Hoisting:
letcũng được hoisting, nhưng không được khởi tạo. Nếu bạn cố gắng truy cập biếnlettrước khi khai báo, bạn sẽ gặp lỗiReferenceError. Vùng này gọi là "Temporal Dead Zone" (TDZ). - Khai báo lại & Gán lại: Không thể khai báo lại biến
lettrong cùng một phạm vi. Tuy nhiên, bạn có thể gán lại giá trị mới cho nó.
// console.log(y); // ReferenceError: Cannot access 'y' before initialization (TDZ)let y = 20;console.log(y); // 20function exampleLet() { let z = 5; if (true) { let z = 10; // Biến z mới, chỉ tồn tại trong khối if console.log(z); // 10 } console.log(z); // 5 (biến z bên ngoài khối if)}exampleLet();let c = 1;// let c = 2; // SyntaxError: Identifier 'c' has already been declaredc = 2; // Gán lại hợp lệconsole.log(c); // 2Const: Biến Hằng Số "Bất Biến" (hay gần như vậy)
- Phạm vi (Scope): Giống như
let,constcũng có phạm vi khối (block scope). - Hoisting: Giống như
let,constcũng được hoisting nhưng nằm trong Temporal Dead Zone. Phải khai báo và gán giá trị ngay lập tức. - Khai báo lại & Gán lại: Không thể khai báo lại và cũng không thể gán lại giá trị cho biến
constsau khi đã khởi tạo.
const PI = 3.14;// PI = 3.14159; // TypeError: Assignment to constant variable.const USER = { name: "Alice", age: 30 };USER.age = 31; // Hợp lệ! Có thể thay đổi thuộc tính của đối tượngconsole.log(USER); // { name: "Alice", age: 31 }// USER = { name: "Bob" }; // TypeError: Assignment to constant variable.Lưu ý quan trọng với const: Khi bạn khai báo một đối tượng hoặc mảng với const, bạn không thể gán lại toàn bộ đối tượng/mảng đó. Tuy nhiên, bạn vẫn có thể thay đổi các thuộc tính bên trong đối tượng hoặc các phần tử của mảng. const đảm bảo rằng tham chiếu đến đối tượng/mảng đó là bất biến, chứ không phải bản thân giá trị bên trong.
Khi nào dùng Var, Let, Const? Thực hành tốt nhất!
Trong lập trình JavaScript hiện đại, hầu hết các developer đều tuân thủ nguyên tắc sau:
- Luôn ưu tiên
const: Nếu biến của bạn không cần thay đổi giá trị sau khi được khởi tạo, hãy dùngconst. Điều này giúp code dễ đọc, dễ bảo trì và tránh được nhiều lỗi tiềm ẩn. - Dùng
letkhi cần gán lại: Nếu bạn biết rằng giá trị của biến sẽ thay đổi trong quá trình thực thi (ví dụ: biến đếm trong vòng lặp, biến lưu trữ kết quả có thể được cập nhật), hãy dùnglet. - Tránh dùng
var: Trong hầu hết các trường hợp, bạn nên tránh sử dụngvarđể hạn chế các vấn đề về phạm vi và hoisting không mong muốn.
Bảng tóm tắt nhanh:
| Đặc điểm | var | let | const |
|---|---|---|---|
| Phạm vi (Scope) | Function scope | Block scope | Block scope |
| Hoisting | Có, với giá trị undefined | Có, nhưng trong TDZ | Có, nhưng trong TDZ |
| Khai báo lại | Có | Không | Không |
| Gán lại | Có | Có | Không (trừ thuộc tính của object/array) |
Việc hiểu rõ và sử dụng đúng var, let, và const không chỉ giúp code của bạn hoạt động chính xác hơn mà còn thể hiện sự chuyên nghiệp và tư duy lập trình hiện đại. Hãy áp dụng ngay những kiến thức này vào dự án của mình để tạo ra những dòng code sạch, mạnh mẽ và dễ bảo trì hơn nhé. Chúc các bạn code vui vẻ!