JavaScript const, let, var: Khi nào nên dùng?
- Home
- JavaScript const, let, var: Khi nào nên dùng?
Khi mới học JavaScript, var, let và const có thể khiến bạn bối rối vì cả ba đều được dùng để khai báo biến. Tuy nhiên, chúng có những khác biệt quan trọng về scope, khả năng gán lại giá trị và hoisting.
Trong JavaScript hiện đại, lựa chọn mặc định nên là const, sau đó dùng let khi biến cần thay đổi giá trị. var chủ yếu nên xuất hiện khi bạn đang làm việc với code JavaScript cũ.
var, let và const khác nhau như thế nào?Ví dụ đơn giản:
var name = "John";
let age = 30;
const country = "Vietnam";
Cả ba đều tạo biến, nhưng hành vi của chúng khác nhau.
| Đặc điểm | var |
let |
const |
|---|---|---|---|
| Có thể gán lại | ✅ | ✅ | ❌ |
| Block scope | ❌ | ✅ | ✅ |
| Function scope | ✅ | ✅ | ✅ |
| Hoisting | Có | Có | Có |
| Temporal Dead Zone | ❌ | ✅ | ✅ |
| Khai báo lại cùng scope | ✅ | ❌ | ❌ |
| Khuyến nghị dùng trong code mới | ❌ | ✅ | ⭐ |
Điểm quan trọng nhất cần nhớ:
const → mặc định
let → khi cần thay đổi giá trị
var → chủ yếu cho code cũ
const – lựa chọn mặc địnhTrong JavaScript hiện đại, hãy ưu tiên const nếu biến không cần được gán lại.
const username = "John";
const age = 30;
const website = "example.com";
Bạn không thể gán giá trị mới cho biến const:
const age = 30;
age = 31;
// TypeError
Điều này giúp code dễ đọc hơn vì khi nhìn thấy const, bạn biết rằng biến đó không được gán sang một giá trị khác.
Ví dụ:
const apiUrl = "/api/users";
const maxRetry = 3;
const timeout = 5000;
Các giá trị cấu hình như vậy rất phù hợp với const.
let – dùng khi giá trị sẽ thay đổiNếu biến cần được gán lại trong quá trình chương trình chạy, hãy dùng let.
Ví dụ:
let count = 0;
count++;
count++;
count++;
console.log(count);
// 3
Hoặc:
let status = "loading";
status = "success";
Một ví dụ thực tế hơn:
let total = 0;
for (let i = 0; i < 10; i++) {
total += i;
}
console.log(total);
Ở đây total và i đều thay đổi giá trị nên let là lựa chọn phù hợp.
var – cách khai báo biến của JavaScript cũTrước ES6, JavaScript chủ yếu sử dụng var.
Ví dụ:
var name = "John";
name = "David";
Code vẫn chạy bình thường.
Tuy nhiên, var có một số đặc điểm dễ gây lỗi, đặc biệt là function scope thay vì block scope.
Đây là lý do var không còn được khuyến khích trong code JavaScript hiện đại.
Đây là một trong những lý do lớn nhất để ưu tiên let và const.
Xét ví dụ:
if (true) {
var name = "John";
}
console.log(name);
Kết quả:
John
var không bị giới hạn bởi block {}.
Trong khi đó:
if (true) {
let name = "John";
}
console.log(name);
Code trên sẽ gây lỗi vì name chỉ tồn tại bên trong block if.
Tương tự với const:
if (true) {
const name = "John";
}
console.log(name);
// ReferenceError
Đây gọi là block scope.
Hãy xem một ví dụ thực tế:
let message = "Hello";
if (true) {
let message = "Welcome";
console.log(message);
}
console.log(message);
Kết quả:
Welcome
Hello
Hai biến message tồn tại ở hai scope khác nhau.
Điều này giúp tránh việc một đoạn code vô tình thay đổi biến được sử dụng ở nơi khác.
const không có nghĩa Object không thể thay đổiĐây là một hiểu lầm rất phổ biến.
Bạn không thể làm:
const user = {
name: "John"
};
user = {
name: "David"
};
Điều này gây lỗi.
Nhưng bạn hoàn toàn có thể thay đổi property của object:
const user = {
name: "John",
age: 30
};
user.name = "David";
user.age = 31;
console.log(user);
Kết quả:
{
name: "David",
age: 31
}
Tại sao?
Bởi vì const ngăn việc gán lại biến, chứ không làm object trở thành immutable.
Bạn có thể khai báo:
const users = [];
Sau đó thêm phần tử:
users.push("John");
users.push("David");
console.log(users);
Kết quả:
["John", "David"]
Nhưng không thể gán một Array mới:
users = ["Peter"];
// TypeError
Vì vậy:
const users = [];
không có nghĩa là Array không thể thay đổi.
Nó chỉ có nghĩa là biến users không thể trỏ sang một Array khác.
var có vấn đề với vòng lặpMột ví dụ kinh điển:
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 100);
}
Kết quả:
3
3
3
Nguyên nhân là var có function scope và cả ba callback đều sử dụng cùng một biến i.
Nếu sử dụng let:
for (let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 100);
}
Kết quả:
0
1
2
Đây là một trong những ví dụ điển hình cho thấy let an toàn hơn var khi làm việc với loop và callback.
var, let, const khác nhauJavaScript có cơ chế hoisting, tức là các khai báo được xử lý trước khi code thực sự chạy.
Với var:
console.log(name);
var name = "John";
Kết quả:
undefined
Có thể hình dung JavaScript xử lý gần giống:
var name;
console.log(name);
name = "John";
let và const cũng được hoist nhưng có Temporal Dead ZoneVí dụ:
console.log(name);
let name = "John";
Code này gây:
ReferenceError
Tương tự:
console.log(name);
const name = "John";
cũng gây lỗi.
Khoảng thời gian từ lúc scope bắt đầu cho tới khi biến được khai báo được gọi là Temporal Dead Zone (TDZ).
Đây thực tế là một điều tốt vì nó giúp phát hiện lỗi sớm hơn.
let và const không thể khai báo lại trong cùng scopeVí dụ:
let name = "John";
let name = "David";
Sẽ gây lỗi.
Với const cũng vậy:
const age = 30;
const age = 31;
Không hợp lệ.
Trong khi var cho phép:
var name = "John";
var name = "David";
console.log(name);
Kết quả:
David
Đây là một trong những hành vi của var có thể khiến code lớn trở nên khó kiểm soát.
constBạn không thể khai báo const mà không gán giá trị:
const username;
Code trên không hợp lệ.
Phải viết:
const username = "John";
Trong khi let có thể:
let username;
username = "John";
Do đó, nếu bạn cần khai báo biến trước rồi mới gán giá trị sau, let phù hợp hơn.
const, let, varBạn có thể sử dụng quy tắc rất đơn giản:
const trướcconst name = "John";
const age = 30;
const users = [];
letlet count = 0;
count++;
var trong code mới// Không nên
var name = "John";
// Nên
const name = "John";
Giả sử bạn xây dựng chức năng lấy danh sách sản phẩm:
const apiUrl = "/api/products";
let products = [];
async function loadProducts() {
const response = await fetch(apiUrl);
products = await response.json();
console.log(products);
}
Ở đây:
const apiUrl
không thay đổi nên dùng const.
let products
có thể được gán dữ liệu mới sau khi API trả về nên dùng let.
Function:
async function loadProducts()
không liên quan trực tiếp đến việc lựa chọn let hay const.
const button = document.querySelector("#submit");
const message = document.querySelector("#message");
let clickCount = 0;
button.addEventListener("click", () => {
clickCount++;
message.textContent = `Clicked ${clickCount} times`;
});
Ở đây:
button → constmessage → constclickCount → letĐây là cách viết rất phổ biến trong JavaScript hiện đại.
const cho mọi thứ?Không.
Một số lập trình viên mới học có xu hướng cố gắng dùng const ở mọi nơi.
Ví dụ:
const count = 0;
count++;
Code này sẽ lỗi.
Nếu giá trị chắc chắn thay đổi:
let count = 0;
count++;
là lựa chọn đúng.
Nguyên tắc không phải là:
“Luôn dùng const.”
Mà là:
Dùng
constkhi không cần gán lại, dùngletkhi cần gán lại.
var?Trong dự án JavaScript mới, bạn gần như không cần var.
Tuy nhiên, var vẫn có thể xuất hiện khi:
Nếu bắt đầu một dự án mới:
const
let
gần như là đủ.
Một style JavaScript phổ biến là:
const API_URL = "/api/users";
const button = document.querySelector("#load");
let loading = false;
button.addEventListener("click", async () => {
loading = true;
const response = await fetch(API_URL);
const users = await response.json();
loading = false;
console.log(users);
});
Bạn có thể thấy một pattern rất rõ:
Không thay đổi → const
Có thay đổi → let
Code legacy → var
var, let và const đều là cách khai báo biến trong JavaScript, nhưng trong JavaScript hiện đại, bạn nên ưu tiên const và let.
Quy tắc đơn giản nhất cần nhớ:
const value = 10;
Dùng const khi biến không được gán lại.
let count = 0;
count++;
Dùng let khi biến cần thay đổi giá trị.
var value = 10;
Hạn chế var trong code mới và chủ yếu gặp nó khi làm việc với legacy JavaScript.
Nếu chưa chắc nên chọn gì, hãy bắt đầu bằng:
const
và chỉ chuyển sang:
let
khi bạn thực sự cần gán lại giá trị.
Đó là cách đơn giản nhất để viết JavaScript hiện đại, dễ đọc và ít lỗi hơn.