Họ đang đo gì
Câu khởi động. Người phỏng vấn muốn biết bạn dùng chính xác từ ngữ hay dùng đại khái.
Trả lời ngắn~30 giây
var có phạm vi hàm và được hoisting với giá trị undefined. let và const có phạm vi khối và nằm trong temporal dead zone cho tới dòng khai báo — truy cập trước đó là ReferenceError chứ không phải undefined. const chặn GÁN LẠI biến, không đóng băng giá trị: const a = []; a.push(1) hoàn toàn hợp lệ.
Giải thích sâu
Khác biệt có hậu quả thật nhất là phạm vi khối trong vòng lặp. Với var, cả vòng lặp dùng CHUNG một biến, nên mọi closure tạo trong vòng lặp đều nhìn thấy giá trị cuối cùng — bug kinh điển “tất cả nút bấm đều in ra 3”. Với let, mỗi lần lặp có một binding riêng, nên mỗi closure giữ đúng giá trị của lượt mình.
Temporal dead zone không phải chi tiết vụn vặt: nó biến một lớp lỗi im lặng thành lỗi ồn ào. Với var, dùng biến trước khi gán cho undefined rồi chương trình chạy tiếp và hỏng ở chỗ khác; với let nó dừng ngay tại dòng gây lỗi. Đó là lý do quy ước hiện nay là dùng const mặc định, let khi cần gán lại, và var thì không dùng nữa.
for (var i = 0; i < 3; i++) setTimeout(() => console.log(i));
// 3 3 3 — một binding duy nhất, đọc sau khi vòng lặp xong
for (let i = 0; i < 3; i++) setTimeout(() => console.log(i));
// 0 1 2 — mỗi lượt một binding riêng
const config = { debug: false };
config.debug = true; // OK: sửa thuộc tính, không gán lại biến
config = {}; // TypeError: Assignment to constant variableCâu hỏi tiếp theo họ sẽ hỏi
?Làm sao để thật sự bất biến?
Object.freeze() cho một tầng, và nó chỉ nông — thuộc tính là object thì vẫn sửa được. Muốn sâu thì phải đệ quy, hoặc dùng cấu trúc bất biến sẵn. Ở TypeScript, readonly và as const chỉ tồn tại lúc biên dịch, chạy thật thì không chặn gì.
Trả lời thế này là mất điểm
- Nói “
constlà hằng số nên không đổi được”. Nửa đầu đúng, nửa sau sai, và nó là nguồn hiểu nhầm thật.