0
0
Lập trình
Sơn Tùng Lê
Sơn Tùng Lê103931498422911686980

So sánh JavaScript let và var: Hướng dẫn cho người mới bắt đầu

Đăng vào 7 tháng trước

• 6 phút đọc

Chủ đề:

#javascript#java

Giới thiệu

Nếu bạn mới bắt đầu hành trình tìm hiểu JavaScript, bạn có thể đã gặp phải nhiều thuật ngữ như function, console.log và tất nhiên là var - cách truyền thống để tạo biến. Trong nhiều năm, var là cách duy nhất để khai báo biến, nhưng nó có nhiều điểm kỳ quặc dẫn đến những lỗi khó chịu cho cả người mới và các lập trình viên có kinh nghiệm.

Năm 2015, JavaScript đã nhận được một bản cập nhật quan trọng với ES6, giới thiệu hai cách mới để khai báo biến: const và let. Hôm nay, chúng ta sẽ cùng tìm hiểu về let, lý do tại sao nó được tạo ra và cách hiểu rõ nó là bước quan trọng trong việc viết mã sạch sẽ và chuyên nghiệp.

Những điểm kỳ quặc của var: Tại sao cần thay đổi?

Để đánh giá cao let, trước tiên chúng ta cần hiểu những vấn đề mà nó khắc phục. Hãy cùng xem hai điểm kỳ quặc lớn nhất của var.

1. Phạm vi function-scoped, không phải block-scoped

Khái niệm quan trọng nhất cần nắm vững là phạm vi (scope). Phạm vi đơn giản là: biến này có sẵn để sử dụng ở đâu?

Biến var có phạm vi là function-scoped, nghĩa là nó chỉ tồn tại trong hàm mà nó được khai báo. Nếu nó không được khai báo trong một hàm, nó sẽ có phạm vi toàn cục (có sẵn ở mọi nơi). Nó không quan tâm đến các câu lệnh if, vòng lặp for hay while. Các dấu ngoặc nhọn {} không tạo ra một phạm vi mới cho var.

Hãy xem ví dụ sau:

javascript Copy
if (true) {
  var message = "Hello from inside the if block!";
  console.log(message); // "Hello from inside the if block!"
}

console.log(message); // "Hello from inside the if block!" (Chờ đã, cái gì?!))

Như bạn thấy, biến message vẫn tồn tại bên ngoài khối if. Điều này có thể gây ra vấn đề vì bạn có thể vô tình ghi đè một biến mà bạn không muốn.

2. Hoisting và sự kỳ quặc của undefined

Hoisting là một hành vi trong JavaScript mà trong đó các khai báo biến và hàm được di chuyển lên đầu phạm vi chứa chúng trong giai đoạn biên dịch. Với var, điều này dẫn đến một tình huống kỳ lạ.

javascript Copy
console.log(myName); // Kết quả: undefined (không phải lỗi!)
var myName = "Alice";
console.log(myName); // Kết quả: "Alice"

Nó không ném ra lỗi ReferenceError! Giống như chúng ta đã viết:

javascript Copy
var myName; // Khai báo "được hoisted" lên đầu và khởi tạo với `undefined`
console.log(myName); // undefined
myName = "Alice"; // Gán giá trị xảy ra ở đây
console.log(myName); // "Alice"

Điều này thật phi lý. Cố gắng sử dụng một biến trước khi nó được khai báo lẽ ra phải là một lỗi, đúng không?

Giới thiệu về let: Người hùng block-scoped

Từ khóa let được giới thiệu để giải quyết những vấn đề này. Nó làm cho các biến hành xử theo cách mà hầu hết các ngôn ngữ lập trình khác làm, tức là hợp lý hơn và ít lỗi hơn.

1. let là block-scoped

Một khối (block) là bất kỳ đoạn mã nào nằm trong một cặp dấu ngoặc nhọn {} - như một câu lệnh if, một vòng lặp for hoặc while. Biến let chỉ tồn tại trong khối mà nó được khai báo.

Hãy xem lại ví dụ ban đầu với let:

javascript Copy
if (true) {
  let message = "Hello from inside the if block!";
  console.log(message); // "Hello from inside the if block!"
}

console.log(message); // ReferenceError: message is not defined

Hooray! Bây giờ chúng ta nhận được một lỗi rõ ràng. Biến message không tồn tại bên ngoài khối mà nó được khai báo. Điều này ngăn chặn việc ô nhiễm phạm vi rộng hơn và làm cho ý định của mã rõ ràng hơn. Nếu một biến chỉ cần thiết bên trong một vòng lặp, nó nên tồn tại và chết bên trong vòng lặp đó.

2. let và The Temporal Dead Zone (TDZ)

Biến let cũng được hoisted, nhưng theo một cách khác, an toàn hơn. Chúng không được khởi tạo với undefined. Thời gian giữa điểm bắt đầu của khối và thời điểm biến được khai báo gọi là Temporal Dead Zone (TDZ). Truy cập biến trong khu vực này sẽ dẫn đến lỗi ReferenceError.

javascript Copy
console.log(favoriteFood); // ReferenceError: Cannot access 'favoriteFood' before initialization
let favoriteFood = "Pizza";

Điều này là tốt! Lỗi là ngay lập tức và rõ ràng, giúp dễ dàng hơn trong việc gỡ lỗi và suy nghĩ về mã của bạn. Nó buộc chúng ta viết mã theo cách có cấu trúc hơn.

let trong vòng lặp: Giải quyết vấn đề cổ điển

Đây có lẽ là ví dụ thực tiễn nhất về lý do tại sao let là một cứu tinh. Hãy xem xét một câu hỏi phỏng vấn cổ điển:

javascript Copy
// Sử dụng var (cách cũ)
for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // Kết quả sẽ là gì?
  }, 100);
}
// Kết quả: 3, 3, 3

Tại sao lại là 3? Bởi vì var có phạm vi function-scoped. Chỉ có một i được chia sẻ bởi cả ba vòng lặp và callback setTimeout. Khi callback chạy, vòng lặp đã kết thúc và i bằng 3.

Bây giờ, hãy thử với let:

javascript Copy
// Sử dụng let (cách hiện đại)
for (let i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // Kết quả sẽ là gì?
  }, 100);
}
// Kết quả: 0, 1, 2

Nó hoạt động! Điều này là vì let có phạm vi block-scoped. Một i mới được tạo ra cho mỗi lần lặp của vòng lặp. Mỗi callback setTimeout giữ một tham chiếu đến i riêng của nó với giá trị chính xác. Điều này loại bỏ một nguồn nhầm lẫn lớn cho các lập trình viên đang tìm hiểu về closures và mã bất đồng bộ.

Khi nào nên sử dụng cái gì?

Dưới đây là một quy tắc đơn giản mà chúng tôi dạy cho sinh viên tại CoderCrafter:

  • Sử dụng const theo mặc định. Nếu bạn biết giá trị của một biến sẽ không bị gán lại, hãy sử dụng const. Điều này làm cho mã của bạn dễ dự đoán hơn và ngăn ngừa việc gán lại không mong muốn.
  • Sử dụng let khi bạn cần gán lại một biến. Nếu bạn biết giá trị sẽ thay đổi (như một biến đếm trong vòng lặp), let là lựa chọn đúng.
  • Tránh sử dụng var. Về cơ bản không cần thiết phải sử dụng var trong các dự án JavaScript hiện đại nữa. Hãy coi nó như một phần của lịch sử, một lời nhắc nhở về sự phát triển của ngôn ngữ.

Kết luận

Hiểu sự khác biệt giữa var và let không chỉ là việc ghi nhớ cú pháp; mà còn là sự hiểu biết về phạm vi, viết mã an toàn hơn và suy nghĩ như một lập trình viên JavaScript hiện đại. Việc chấp nhận let và const là dấu hiệu cho thấy bạn đã vượt qua việc viết mã cơ bản và đang tiến vào phát triển phần mềm nghiêm túc.

Những khái niệm cốt lõi về phạm vi, hoisting và closures tạo thành nền tảng của JavaScript. Làm chủ chúng là điều không thể thiếu cho bất kỳ ai muốn xây dựng ứng dụng web mạnh mẽ.

Nếu bạn cảm thấy hứng thú với việc tìm hiểu sâu về các khái niệm cơ bản của JavaScript, còn rất nhiều điều thú vị để khám phá! Thế giới phát triển full-stack là rộng lớn và cực kỳ bổ ích. Tại CoderCrafter, các khóa học Phát triển Full Stack và MERN Stack của chúng tôi được thiết kế để giúp bạn từ người mới bắt đầu trở thành lập trình viên sẵn sàng cho công việc. Chúng tôi không chỉ dạy bạn cú pháp; chúng tôi dạy bạn lý do phía sau mã, giúp bạn xây dựng một nền tảng vững chắc cho sự nghiệp thành công trong lĩnh vực công nghệ.

Sẵn sàng chinh phục JavaScript và xây dựng những điều tuyệt vời? Hãy truy cập codercrafter.in hôm nay để khám phá các khóa học của chúng tôi và đăng ký cho tương lai của bạn!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào