Khai báo và sử dụng biến let trong JavaScript

Javascript căn bản | by Học Javascript

Trong JavaScript, biến đóng vai trò quan trọng trong việc lưu trữ và quản lý dữ liệu. Việc khai báo biến đúng cách giúp mã nguồn dễ đọc, bảo trì và tránh các lỗi không mong muốn. Trước đây, JavaScript chỉ có từ khóa var để khai báo biến, nhưng nó có một số hạn chế như không có phạm vi khối (block scope) và dễ gây lỗi do hoisting.

Với sự ra đời của ES6, từ khóa let đã được giới thiệu để thay thế var trong nhiều trường hợp, giúp lập trình viên kiểm soát phạm vi biến tốt hơn và giảm thiểu lỗi. Trong bài viết này, mình sẽ tìm hiểu cách khai báo và sử dụng biến let trong JavaScript, cũng như so sánh sự khác biệt giữa letvar để hiểu rõ hơn về cách sử dụng hiệu quả.

Khai báo biến với let trong JavaScript

Cú pháp khai báo biến với let

Từ khóa let trong JavaScript được sử dụng để khai báo biến với phạm vi khối (block scope). Khi khai báo biến bằng let, bạn có thể gán giá trị ngay lập tức hoặc để trống và gán giá trị sau.

Cú pháp:

let tenBien; // Khai báo một biến nhưng chưa gán giá trị
let soLuong = 10; // Khai báo và gán giá trị ngay lập tức
let ten = "Nguyễn Văn A"; // Khai báo và gán giá trị kiểu chuỗi

Ví dụ minh họa:

let x; // Khai báo biến x
console.log(x); // Kết quả: undefined (biến được khai báo nhưng chưa gán giá trị)

let y = 5; // Khai báo biến y với giá trị ban đầu là 5
console.log(y); // Kết quả: 5

y = 10; // Gán lại giá trị mới cho y
console.log(y); // Kết quả: 10

Kết quả:

Trong ví dụ trên:

  • x được khai báo nhưng chưa có giá trị, do đó khi in ra sẽ là undefined.
  • y được khai báo với giá trị 5, sau đó giá trị của y được thay đổi thành 10.

Đặc điểm của biến khai báo bằng let

Không thể khai báo lại cùng một tên biến trong cùng một phạm vi

Khi khai báo biến bằng let, nếu bạn cố gắng khai báo lại một biến có cùng tên trong cùng một phạm vi, JavaScript sẽ báo lỗi.

Ví dụ minh họa:

let a = 10;
let a = 20; // Lỗi: Identifier 'a' has already been declared

Lỗi trên xảy ra vì biến a đã được khai báo bằng let và không thể khai báo lại trong cùng một phạm vi.

Tuy nhiên, nếu biến a được khai báo trong các phạm vi khác nhau (ví dụ: trong một khối {} khác), thì nó sẽ không gây lỗi:

let b = 30;
{
    let b = 40; // Hợp lệ, vì biến b này nằm trong một phạm vi khối khác
    console.log(b); // Kết quả: 40
}
console.log(b); // Kết quả: 30

Trong đoạn mã trên:

  • Biến b trong khối {} là một biến khác, độc lập với biến b bên ngoài.
  • Phạm vi của b bên trong {} chỉ có hiệu lực trong khối đó.

Có thể gán lại giá trị sau khi khai báo

Một trong những đặc điểm quan trọng của let là bạn có thể gán lại giá trị cho biến sau khi đã khai báo.

Ví dụ minh họa:

let diem = 8;
console.log(diem); // Kết quả: 8

diem = 9; // Gán lại giá trị mới
console.log(diem); // Kết quả: 9

Ở đây, biến diem được khai báo với giá trị ban đầu là 8, sau đó giá trị của nó được cập nhật thành 9. Điều này giúp let linh hoạt hơn so với const, vì const không cho phép gán lại giá trị sau khi khai báo.

Phạm vi hoạt động của let (Block Scope) trong JavaScript

Giải thích về phạm vi khối của let

Trong JavaScript, phạm vi (scope) của một biến quyết định nơi biến đó có thể được truy cập. Biến khai báo bằng letphạm vi khối (block scope), nghĩa là nó chỉ tồn tại và có thể truy cập được bên trong khối {} mà nó được khai báo.

Khối {} có thể là:

  • Một khối lệnh trong if, for, while, hoặc switch.
  • Một cặp {} độc lập trong mã nguồn.

Nếu cố gắng truy cập biến let bên ngoài phạm vi khối {}, JavaScript sẽ báo lỗi.

Ví dụ minh họa về phạm vi khối của let:

{
    let x = 10;
    console.log(x); // Kết quả: 10 (Biến x tồn tại trong khối này)
}
console.log(x); // Lỗi: x is not defined (Không thể truy cập biến x ngoài khối {})

Kết quả:

Ở đây:

  • Biến x được khai báo bên trong {} nên nó chỉ tồn tại trong phạm vi của khối đó.
  • Khi cố gắng truy cập x bên ngoài khối, chương trình báo lỗi vì x không tồn tại ngoài phạm vi khối.

So sánh let với var (Phạm Vi Hàm)

Đặc điểm let (Phạm vi khối) var (Phạm vi hàm)
Phạm vi Chỉ tồn tại trong {} nơi nó được khai báo Tồn tại trong toàn bộ hàm chứa nó
Có thể khai báo lại trong cùng một phạm vi không? Không
Bị ảnh hưởng bởi hoisting không? Có nhưng không thể sử dụng trước khi khai báo (TDZ - Temporal Dead Zone) Có, giá trị mặc định là undefined nếu sử dụng trước khi khai báo

Ví dụ minh họa so sánh let và var:

function testVar() {
    if (true) {
        var a = 10;
    }
    console.log(a); // Kết quả: 10 (Vẫn truy cập được vì var có phạm vi hàm)
}
testVar();
function testLet() {
    if (true) {
        let b = 20;
    }
    console.log(b); // Lỗi: b is not defined (Không thể truy cập biến b ngoài khối if)
}
testLet();

Giải thích:

  • var a tồn tại trong toàn bộ hàm, dù nó được khai báo bên trong if.
  • let b chỉ tồn tại trong khối if, nên khi truy cập ngoài if, chương trình báo lỗi.

Ví dụ minh họa phạm vi hoạt động của let trong một khối {}

Ví dụ 1: let bên trong vòng lặp for
for (let i = 0; i < 3; i++) {
    console.log(i); // Kết quả: 0, 1, 2
}
console.log(i); // Lỗi: i is not defined (Vì biến i chỉ tồn tại trong vòng lặp)

Ở đây, biến i chỉ tồn tại trong phạm vi {} của vòng lặp for. Khi cố gắng truy cập i bên ngoài vòng lặp, chương trình báo lỗi.

Ví dụ 2: let trong nhiều khối khác nhau

{
    let x = 5;
    console.log(x); // Kết quả: 5
}
{
    let x = 10;
    console.log(x); // Kết quả: 10 (X này khác với X ở khối trước)
}
Mỗi khối {} có một biến x riêng biệt, và chúng không ảnh hưởng lẫn nhau.

Sử dụng let trong chương trình JavaScript

Khai báo và gán giá trị cho biến

Trong JavaScript, biến khai báo bằng let có thể lưu trữ nhiều loại dữ liệu khác nhau như số (number), chuỗi (string), mảng (array), và đối tượng (object).

Ví dụ minh họa với số, chuỗi, mảng, và đối tượng

Khai báo và gán giá trị số (number)

let soLuong = 10; 
console.log(soLuong); // Kết quả: 10

soLuong = 20; // Gán lại giá trị mới
console.log(soLuong); // Kết quả: 20

Giải thích:

  • Biến soLuong được khai báo với giá trị ban đầu là 10.
  • Sau đó, giá trị của biến soLuong được cập nhật thành 20.

Khai báo và gán giá trị chuỗi (string)

let hoTen = "Nguyễn Văn A";
console.log(hoTen); // Kết quả: Nguyễn Văn A

hoTen = "Trần Thị B"; // Gán lại giá trị mới
console.log(hoTen); // Kết quả: Trần Thị B

Giải thích:

  • Biến hoTen chứa một chuỗi.
  • Có thể thay đổi giá trị của chuỗi bằng cách gán lại một giá trị mới.

Khai báo và gán giá trị mảng (array)

let danhSach = [1, 2, 3, 4, 5];
console.log(danhSach); // Kết quả: [1, 2, 3, 4, 5]

danhSach[0] = 10; // Thay đổi phần tử đầu tiên của mảng
console.log(danhSach); // Kết quả: [10, 2, 3, 4, 5]

Giải thích:

  • Mảng danhSach có thể thay đổi giá trị của từng phần tử bên trong.

Khai báo và gán giá trị đối tượng (object)

let nguoi = {
    ten: "Nguyễn Văn A",
    tuoi: 25
};
console.log(nguoi); // Kết quả: {ten: "Nguyễn Văn A", tuoi: 25}

nguoi.tuoi = 30; // Thay đổi giá trị thuộc tính
console.log(nguoi); // Kết quả: {ten: "Nguyễn Văn A", tuoi: 30}

Giải thích:

  • Đối tượng nguoi có thể thay đổi giá trị thuộc tính (tuoi từ 25 thành 30).

Sử dụng let trong vòng lặp trong JavaScript

Biến khai báo bằng let thường được sử dụng trong các vòng lặp như forwhile.

Ví dụ minh họa với vòng lặp for

for (let i = 0; i < 5; i++) {
    console.log("Giá trị của i: " + i);
}
console.log(i); // Lỗi: i is not defined (i chỉ tồn tại trong vòng lặp)

Giải thích:

  • Biến i chỉ tồn tại bên trong vòng lặp for, khi vòng lặp kết thúc, i không thể truy cập từ bên ngoài.

Ví dụ minh họa với vòng lặp while

let j = 0;
while (j < 3) {
    console.log("Giá trị của j: " + j);
    j++;
}
console.log("Giá trị cuối cùng của j: " + j); // Kết quả: 3

Giải thích:

  • j được khai báo bên ngoài while, nên sau khi vòng lặp kết thúc, nó vẫn có thể truy cập được.

Sử dụng let trong câu lệnh điều kiện trong JavaScript

Biến let có thể được sử dụng trong các câu lệnh điều kiện if, else if, và else để kiểm tra và xử lý dữ liệu.

Ví dụ với if, else if, else

let diem = 85;

if (diem >= 90) {
    console.log("Xếp loại: Xuất sắc");
} else if (diem >= 75) {
    console.log("Xếp loại: Giỏi");
} else if (diem >= 50) {
    console.log("Xếp loại: Trung bình");
} else {
    console.log("Xếp loại: Yếu");
}

Giải thích:

  • Biến diem có giá trị 85, nên khối else if (diem >= 75) sẽ được thực thi, và in ra "Xếp loại: Giỏi".
  • Nếu diem = 95, kết quả sẽ là "Xếp loại: Xuất sắc".

Ví dụ với if bên trong một khối {}

let tuoi = 18;

if (tuoi >= 18) {
    let thongBao = "Bạn đã đủ tuổi trưởng thành.";
    console.log(thongBao);
}
console.log(thongBao); // Lỗi: thongBao is not defined

Giải thích:

  • Biến thongBao được khai báo bên trong khối {} của if, nên nó chỉ tồn tại trong khối đó.
  • Khi cố gắng truy cập thongBao bên ngoài if, JavaScript báo lỗi.

Lỗi thường gặp khi sử dụng let trong JavaScript

Biến let giúp quản lý dữ liệu hiệu quả hơn trong JavaScript, nhưng nếu không hiểu rõ cách hoạt động, bạn có thể gặp phải một số lỗi phổ biến. Dưới đây là ba lỗi thường gặp khi sử dụng let và cách tránh chúng.

Sử dụng biến trước khi khai báo (Temporal Dead Zone)

Khi sử dụng let, bạn không thể truy cập biến trước khi nó được khai báo trong phạm vi của nó. Điều này xảy ra do Temporal Dead Zone (TDZ) – một khoảng thời gian mà biến tồn tại nhưng chưa được khởi tạo.

Ví dụ lỗi:

console.log(a); //  Lỗi: Cannot access 'a' before initialization
let a = 10;
console.log(a); // Kết quả: 10

Giải thích:

  • Khi truy cập a trước khi khai báo, trình thông dịch báo lỗi vì a đang nằm trong Temporal Dead Zone.
  • Chỉ sau khi a được khai báo (let a = 10;), ta mới có thể sử dụng nó.

Cách tránh lỗi:

  • Luôn khai báo biến trước khi sử dụng.
  • Nếu cần sử dụng biến trước, hãy gán giá trị mặc định cho nó.

Khai báo trùng tên biến trong cùng một phạm vi

Biến khai báo bằng let không thể được khai báo lại trong cùng một phạm vi. Nếu cố tình khai báo trùng tên biến, JavaScript sẽ báo lỗi.

Ví dụ lỗi:

let x = 5;
let x = 10; //  Lỗi: Identifier 'x' has already been declared

Giải thích:

  • JavaScript không cho phép khai báo lại biến x trong cùng một phạm vi.
  • Điều này giúp tránh lỗi vô tình ghi đè giá trị biến.

Ví dụ với let trong các phạm vi khác nhau:

let y = 20;

if (true) {
    let y = 30; //  Không lỗi, vì biến này thuộc phạm vi khối {}
    console.log(y); // Kết quả: 30
}

console.log(y); // Kết quả: 20 (biến y bên ngoài không bị ảnh hưởng)

Giải thích:

  • Biến y trong if là một biến mới, khác với biến y bên ngoài.
  • Biến y bên trong chỉ tồn tại trong khối {}, không ảnh hưởng đến biến y bên ngoài.

Kết bài

Trong bài viết này, mình đã tìm hiểu về việc khai báo và sử dụng biến với từ khóa let trong JavaScript, một phần quan trọng trong việc xây dựng các ứng dụng web. Từ việc khai báo biến, hiểu được phạm vi hoạt động của biến (block scope), cho đến việc tránh các lỗi thường gặp như sử dụng biến trước khi khai báo, khai báo trùng tên, và truy cập biến ngoài phạm vi, chúng ta đã nắm bắt được những nguyên tắc cơ bản để sử dụng let một cách hiệu quả.

Nhờ khả năng kiểm soát phạm vi tốt hơn so với var, let giúp việc quản lý dữ liệu trong chương trình trở nên an toàn và dễ dàng hơn, đặc biệt trong các cấu trúc điều kiện và vòng lặp. Tuy nhiên, để tận dụng tối đa khả năng của let, bạn cần hiểu rõ cách khai báo và sử dụng đúng đắn để tránh các lỗi không mong muốn.

Khi bạn làm quen và thực hành với let trong các dự án thực tế, bạn sẽ thấy rằng nó giúp mã nguồn trở nên rõ ràng, dễ bảo trì và ít gặp phải các lỗi khó phát hiện. Việc hiểu và áp dụng tốt các khái niệm về biến trong JavaScript sẽ là nền tảng vững chắc để bạn tiếp tục phát triển kỹ năng lập trình của mình.

Bài viết liên quan

  • 2