Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Khai báo lại biến (re-declare) trong JavaScript: Kết quả như thế nào?

Trong JavaScript, khai báo lại biến cùng tên với var không gây lỗi và không reset giá trị. Đây là hành vi cho phép nhưng có thể dẫn đến bug nếu không cẩn thận.

Hành vi với var


var age = 20;
var age;        // Khai báo lại - KHÔNG LÀM GÌ (giá trị giữ nguyên)
console.log(age); // 20

var age = 30;   // Khai báo + gán - GIÁ TRỊ THAY ĐỔI
console.log(age); // 30

Quy tắc: var name; đơn lẻ (không gán giá trị) là no-op nếu biến đã tồn tại trong scope. Chỉ var name = value; mới gán giá trị mới.

Ví dụ từ bài gốc


<script>
  var age = 20;
  var age;        // Không thay đổi age
  if (age > 18) {
    document.write("Đủ điều kiện lái xe"); // Chạy
  }
</script>

Khác biệt với let và const (ES6)


let x = 1;
let x = 2; // SyntaxError: Identifier 'x' has already been declared

const y = 1;
const y = 2; // SyntaxError

// Trong block khác thì OK
let a = 1;
{
  let a = 2; // OK - block scope khác
  console.log(a); // 2
}
console.log(a); // 1

Function Scope vs Block Scope


// var: function scope
function foo() {
  var x = 1;
  if (true) {
    var x = 2; // Cùng biến!
    console.log(x); // 2
  }
  console.log(x); // 2 (biến outer bị thay đổi)
}

// let/const: block scope
function bar() {
  let y = 1;
  if (true) {
    let y = 2; // Biến mới, shadowing
    console.log(y); // 2
  }
  console.log(y); // 1 (biến outer không đổi)
}

Tại sao var cho phép re-declare?

  • Thiết kế ban đầu cho script nhỏ, linh hoạt.
  • Hoisting: nhiều var x gộp thành một khai báo ở đầu scope.
  • Tương thích ngược (backward compatibility) – không thể bỏ.

Best Practice

  • Luôn dùng let/const – báo lỗi ngay khi trùng khai báo.
  • Bật "use strict" hoặc ESLint rule no-redeclare.
  • Tránh khai báo biến trùng tên trong cùng scope – gây nhầm lẫn.
  • Dùng block { } để tạo scope cục bộ cho biến tạm.

Tóm tắt

Từ khóaKhai báo lại cùng scopeGán lại giá trị
varCho phép (chỉ khai báo: no-op)Cho phép
letCấm (SyntaxError)Cho phép
constCấm (SyntaxError)Cấm (TypeError)