Khai báo biến trùng tên trong cùng scope gây nhầm lẫn, bug. Cách ngăn chặn tốt nhất: dùng Block Scope (let/const) và Module/IIFE để cách ly scope.
Vấn đề với var (Function Scope)
function foo() {
var x = 1;
if (true) {
var x = 2; // CÙNG BIẾN! (var không quan tâm block)
console.log(x); // 2
}
console.log(x); // 2 (biến outer đã bị thay đổi)
}
Giải pháp 1: Dùng let/const (Block Scope) – ES6+
function foo() {
let x = 1;
if (true) {
let x = 2; // BIẾN MỚI (block scope) - shadowing an toàn
console.log(x); // 2
}
console.log(x); // 1 (biến outer không đổi)
}
Giải pháp 2: IIFE (Immediately Invoked Function Expression) – Legacy pattern
Bài gốc gợi ý dùng IIFE để tạo scope riêng:
(function() {
var rank = 1; // Chỉ tồn tại trong IIFE này
// code sử dụng rank...
}());
// rank KHÔNG truy cập được bên ngoài
console.log(typeof rank); // "undefined"
Đây là pattern phổ biến trước ES6 (module pattern). Hiện nay dùng ES Modules (import/export) hoặc block scope.
Giải pháp 3: ES Modules (Hiện đại, chuẩn)
export const rank = 1; // Chỉ xuất rank, không ô nhiễm global
import { rank } from './module.js';
// rank chỉ có trong scope module này
Mỗi file module có scope riêng, không chia sẻ global scope.
Giải pháp 4: Linting (Phát hiện sớm)
Cấu hình ESLint:
{
"rules": {
"no-redeclare": "error", // Cấm redeclare trong cùng scope
"no-shadow": "error", // Cấm shadowing biến outer
"no-unused-vars": "warn" // Cảnh báo biến không dùng
}
}
Giải pháp 5: TypeScript (Compile-time check)
let x = 1;
let x = 2; // Error: Cannot redeclare block-scoped variable 'x'.
// Block scope an toàn
{
let x = 2; // OK - block scope khác
}
So sánh các cách
| Cách | Scope cách ly | Hiện đại | Khuyến nghị |
|---|---|---|---|
let/const (Block scope) | Block { } | ✅ | ✅ Mặc định |
| ES Modules | File | ✅ | ✅ Dự án lớn |
| IIFE | Function | ❌ (Legacy) | Chỉ code cũ |
| ESLint/TypeScript | Static analysis | ✅ | ✅ Bắt buộc |
Tóm tắt
- Dùng
let/const→ Block scope tự nhiên ngăn duplicate/shadowing nguy hiểm. - Dùng ES Modules → File scope, cách ly hoàn toàn.
- Bật ESLint
no-redeclare,no-shadow. - Tránh
varvà IIFE trong code mới.