Cách sử dụng vòng lặp for...of trong JavaScript

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

Trong JavaScript, vòng lặp là một công cụ quan trọng giúp chúng ta lặp đi lặp lại một khối lệnh trên các tập hợp dữ liệu như mảng, chuỗi, Set, Map, v.v. Trong số các vòng lặp có sẵn, for...of là một lựa chọn mạnh mẽ và dễ sử dụng để duyệt qua các phần tử của một iterable object một cách trực quan và hiệu quả.

Không giống như for...in, vốn được sử dụng để lặp qua các thuộc tính của một object, for...of tập trung vào giá trị của các phần tử trong tập hợp dữ liệu. Điều này giúp mã nguồn trở nên gọn gàng và dễ đọc hơn, đặc biệt khi làm việc với mảng (Array), chuỗi (String), tập hợp (Set), và bản đồ (Map).

Bài viết này sẽ hướng dẫn chi tiết cách sử dụng vòng lặp for...of, các trường hợp áp dụng, điểm khác biệt so với các vòng lặp khác, cũng như những lưu ý quan trọng khi sử dụng trong thực tế.

Vòng lặp for...of trong JavaScript

Vòng lặp for...of trong JavaScript được sử dụng để duyệt qua các phần tử của một iterable object (đối tượng có thể lặp được), chẳng hạn như mảng (Array), chuỗi (String), tập hợp (Set), bản đồ (Map), và nhiều kiểu dữ liệu khác.

Cấu trúc của vòng lặp for...of:

for (let element of iterable) {
    // Thực hiện các thao tác với element
}
  • iterable: Một đối tượng có thể lặp qua, như mảng, chuỗi, Set, Map, v.v.
  • element: Giá trị của từng phần tử trong iterable.

Ví dụ đơn giản với một mảng (Array):

const numbers = [1, 2, 3, 4, 5];

for (let num of numbers) {
    console.log(num);  // Output: 1, 2, 3, 4, 5
}

Ở đây, num lần lượt nhận giá trị của từng phần tử trong mảng numbers.

Khi nào nên sử dụng for...of?

Vòng lặp for...of đặc biệt hữu ích trong các trường hợp sau:

Duyệt qua từng phần tử của một tập hợp dữ liệu mà không cần quan tâm đến chỉ mục (index). Ví dụ: khi làm việc với mảng hoặc Set, for...of giúp mã nguồn dễ đọc hơn so với vòng lặp for.

Duyệt qua từng ký tự của chuỗi (String) một cách đơn giản.

Duyệt qua giá trị của Map hoặc Set mà không cần sử dụng Object.keys() hoặc Object.entries().

Làm việc với các cấu trúc dữ liệu iterable như NodeList (kết quả của document.querySelectorAll() trong DOM), TypedArray, hoặc arguments trong hàm.

Ví dụ: Lặp qua từng ký tự trong một chuỗi:

const text = "Hello";

for (let char of text) {
    console.log(char);  // Output: H, e, l, l, o
}

So sánh for...of với các vòng lặp khác

Vòng lặp Đặc điểm chính Khi nào sử dụng?
for Duyệt qua các phần tử theo chỉ mục. Cần xác định điều kiện lặp. Khi cần thao tác với chỉ mục hoặc có logic phức tạp về số lần lặp.
forEach() Duyệt qua từng phần tử của mảng nhưng không thể break hay continue. Khi cần duyệt qua mảng mà không cần thoát vòng lặp sớm.
for...in Duyệt qua các key của một object (hoặc chỉ mục của mảng, nhưng không khuyến khích). Khi cần lặp qua các thuộc tính của object.
for...of Duyệt qua từng giá trị của iterable object. Khi cần duyệt qua mảng, chuỗi, Set, Map một cách đơn giản.

Ví dụ so sánh for...offor...in khi làm việc với mảng

const numbers = [10, 20, 30];

// for...in (Lặp qua chỉ mục)
for (let index in numbers) {
    console.log(index);  // Output: 0, 1, 2
}

// for...of (Lặp qua giá trị)
for (let value of numbers) {
    console.log(value);  // Output: 10, 20, 30
}

Khi làm việc với mảng, for...of được ưu tiên hơn for...in vì nó trả về giá trị của phần tử thay vì chỉ mục.

Ví dụ so sánh for...offorEach()

const colors = ["red", "green", "blue"];

// forEach()
colors.forEach(color => console.log(color));  // Output: red, green, blue

// for...of
for (let color of colors) {
    console.log(color);  // Output: red, green, blue
}

Lưu ý:

  • forEach() không thể bị break hoặc continue giữa chừng, trong khi for...of có thể.
  • forEach() có thể truyền thêm index và context (this), nhưng for...of chỉ đơn giản lấy giá trị phần tử.

Cú pháp vòng lặp for...of trong JavaScript

Cấu trúc chung của for...of

Vòng lặp for...of trong JavaScript có cú pháp đơn giản và dễ đọc. Nó được sử dụng để lặp qua các phần tử của một iterable object như mảng (Array), chuỗi (String), tập hợp (Set), bản đồ (Map), v.v.

Cú pháp chung:

for (let element of iterable) {
    // Thực hiện thao tác với từng phần tử
}

Trong đó:

  • iterable: Là một đối tượng có thể lặp được (mảng, chuỗi, Set, Map, v.v.).
  • element: Đại diện cho từng phần tử của iterable trong mỗi lần lặp.

Ví dụ đơn giản với mảng (Array)

Mảng là một trong những kiểu dữ liệu phổ biến nhất mà vòng lặp for...of có thể duyệt qua.

Ví dụ 1: Duyệt qua các phần tử của một mảng số

const numbers = [10, 20, 30, 40, 50];

for (let num of numbers) {
    console.log(num);
}

Kết quả:

10
20
30
40
50
  • Mỗi lần lặp, num sẽ lấy giá trị của từng phần tử trong mảng numbers.
  • for...of giúp duyệt mảng một cách trực quan mà không cần quan tâm đến chỉ mục như vòng lặp for thông thường.

Ví dụ 2: Duyệt qua một mảng chuỗi

const fruits = ["Apple", "Banana", "Cherry"];

for (let fruit of fruits) {
    console.log(fruit);
}

Kết quả:

Apple
Banana
Cherry

Trong mỗi lần lặp, fruit sẽ nhận giá trị của từng phần tử trong mảng fruits.

Cách này đơn giản hơn so với việc sử dụng vòng lặp for truyền thống.

Sử dụng for...of với các kiểu dữ liệu khác nhau trong JavaScript

Vòng lặp for...of trong JavaScript có thể được sử dụng để duyệt qua nhiều kiểu dữ liệu khác nhau, miễn là chúng có tính chất iterable (có thể lặp qua). Dưới đây là cách sử dụng for...of với mảng (Array), chuỗi (String), tập hợp (Set), và bản đồ (Map), cùng với các ví dụ minh họa.

Sử dụng với mảng (Array)

Cách lặp qua các phần tử của mảng

Mảng (Array) là một kiểu dữ liệu phổ biến mà for...of có thể duyệt qua một cách dễ dàng.

Ví dụ: Duyệt qua các phần tử trong một mảng

const numbers = [1, 2, 3, 4, 5];

for (let num of numbers) {
    console.log(num);
}

Kết quả:

1
2
3
4
5
  • rong mỗi lần lặp, num sẽ lấy giá trị của từng phần tử trong mảng numbers.

So sánh for...of, forEach(), và for...in khi lặp qua mảng

Vòng lặp Hoạt động Khi nào nên dùng?
for...of Duyệt qua từng phần tử trong mảng theo giá trị. Hỗ trợ breakcontinue. Khi cần duyệt qua các phần tử của mảng một cách trực quan, có thể dừng hoặc bỏ qua lần lặp.
forEach() Duyệt qua từng phần tử, nhưng không hỗ trợ break hoặc continue. Khi cần thực hiện một hành động trên từng phần tử của mảng mà không cần dừng vòng lặp.
for...in Duyệt qua chỉ mục (index) của mảng (không khuyến khích dùng với mảng). Khi cần làm việc với index, nhưng tốt hơn nên dùng for thông thường.

Ví dụ so sánh

const fruits = ["Apple", "Banana", "Cherry"];

// for...of
for (let fruit of fruits) {
    console.log(fruit);  // Output: Apple, Banana, Cherry
}

// forEach()
fruits.forEach(fruit => console.log(fruit));  // Output: Apple, Banana, Cherry

// for...in
for (let index in fruits) {
    console.log(index, fruits[index]);  // Output: 0 Apple, 1 Banana, 2 Cherry
}

Lưu ý: for...in không được khuyến khích dùng với mảng vì nó trả về chỉ mục thay vì giá trị.

Sử dụng với chuỗi (String)

Lặp qua từng ký tự trong chuỗi

Chuỗi (String) cũng là một kiểu dữ liệu có thể lặp qua bằng for...of.

Ví dụ: Lặp qua từng ký tự của chuỗi

const text = "Hello";

for (let char of text) {
    console.log(char);
}

Kết quả:

H
e
l
l
o
  • Mỗi lần lặp, char nhận một ký tự từ chuỗi text.
  • Dùng for...of với chuỗi giúp duyệt qua từng ký tự một cách đơn giản, không cần dùng charAt() hoặc truy cập theo chỉ mục.

Sử dụng với Set

Lặp qua các phần tử trong Set

Tập hợp (Set) là một cấu trúc dữ liệu không chứa các phần tử trùng lặp. Vòng lặp for...of có thể duyệt qua từng phần tử trong Set.

Ví dụ: Duyệt qua Set

const uniqueNumbers = new Set([1, 2, 3, 4, 5]);

for (let num of uniqueNumbers) {
    console.log(num);
}

Kết quả:

1
2
3
4
5
  • Set không có chỉ mục, nên for...in không thể sử dụng để duyệt qua.
  • for...of là cách duyệt tốt nhất khi làm việc với Set.

Sử dụng với Map

Lặp qua các cặp key-value trong Map

Bản đồ (Map) là một cấu trúc dữ liệu lưu trữ các cặp key-value. for...of có thể được sử dụng để duyệt qua cả key, value, hoặc cả hai.

Ví dụ 1: Lặp qua toàn bộ Map (key-value)

const userInfo = new Map([
    ["name", "Alice"],
    ["age", 25],
    ["city", "New York"]
]);

for (let [key, value] of userInfo) {
    console.log(`${key}: ${value}`);
}

Kết quả:

name: Alice
age: 25
city: New York
  • for...of giúp lấy cả key và value cùng lúc khi dùng let [key, value].

Ví dụ 2: Lặp qua chỉ keys hoặc chỉ values

// Duyệt qua keys
for (let key of userInfo.keys()) {
    console.log(key);
}
// Output: name, age, city

// Duyệt qua values
for (let value of userInfo.values()) {
    console.log(value);
}
// Output: Alice, 25, New York
  • .keys() trả về danh sách các key trong Map.
  • .values() trả về danh sách các value trong Map.

Lưu ý và hạn chế của for...of trong JavaScript

Vòng lặp for...of rất hữu ích để duyệt qua các phần tử trong mảng (Array), chuỗi (String), tập hợp (Set), bản đồ (Map), nhưng nó có một số hạn chế cần lưu ý:

for...of không thể sử dụng trực tiếp với Object

for...of không thể sử dụng trực tiếp với Object thông thường, bởi vì Object không phải là một iterable object. Nếu cố gắng dùng for...of để lặp qua một Object, sẽ gặp lỗi:

Ví dụ: Dùng for...of với Object gây lỗi

const person = { name: "Alice", age: 25, city: "New York" };

for (let key of person) {
    console.log(key);
}

Lỗi xuất hiện:

Uncaught TypeError: person is not iterable

Giải thích:

  • for...of chỉ hoạt động với các đối tượng có thuộc tính Symbol.iterator như Array, String, Set, Map.
  • Object không phải là một iterable object, vì vậy không thể sử dụng for...of trực tiếp.

Cách xử lý Object với for...of

Mặc dù không thể sử dụng for...of trực tiếp với Object, nhưng chúng ta có thể chuyển đổi Object thành một mảng bằng cách sử dụng:

  • Object.keys() → Lấy danh sách key của Object.
  • Object.values() → Lấy danh sách value của Object.
  • Object.entries() → Lấy danh sách cặp key-value của Object dưới dạng mảng.

Sử dụng Object.keys() để duyệt qua key của Object

Phương thức Object.keys(object) trả về một mảng chứa tất cả các key của Object, sau đó có thể dùng for...of để lặp qua.

Ví dụ: Lặp qua key của Object

const person = { name: "Alice", age: 25, city: "New York" };

for (let key of Object.keys(person)) {
    console.log(key);
}

Kết quả:

name
age
city

Lưu ý: Object.keys() chỉ trả về danh sách key, không bao gồm giá trị.

Sử dụng Object.values() để duyệt qua giá trị của Object

Nếu chỉ cần duyệt qua giá trị (value) của Object, có thể dùng Object.values(object).

Ví dụ: Lặp qua giá trị của Object

const person = { name: "Alice", age: 25, city: "New York" };

for (let value of Object.values(person)) {
    console.log(value);
}

Kết quả:

Alice
25
New York

Ứng dụng: Cách này hữu ích khi chỉ quan tâm đến dữ liệu, không cần key.

Sử dụng Object.entries() để duyệt qua cả key và value của Object

Object.entries(object) trả về một mảng chứa các cặp [key, value], giúp duyệt qua cả key và value của Object.

Ví dụ: Lặp qua cả key và value

const person = { name: "Alice", age: 25, city: "New York" };

for (let [key, value] of Object.entries(person)) {
    console.log(`${key}: ${value}`);
}

Kết quả:

name: Alice
age: 25
city: New York

Ứng dụng: Dùng khi cần truy cập cả key và value của Object.

Khi nào nên sử dụng for...of và khi nào nên dùng for...in?

Vòng lặp Khi nào nên dùng? Hạn chế
for...of Khi duyệt qua mảng, chuỗi, Set, Map, hoặc bất kỳ iterable object nào. Không hoạt động với Object.
for...in Khi cần duyệt qua key của một Object. Không duyệt qua giá trị, có thể lặp cả thuộc tính kế thừa.

Ví dụ so sánh for...infor...of với Object

const person = { name: "Alice", age: 25, city: "New York" };

// Dùng for...in
console.log("Duyệt bằng for...in:");
for (let key in person) {
    console.log(key, person[key]);
}

// Dùng for...of (phải kết hợp Object.entries)
console.log("\nDuyệt bằng for...of:");
for (let [key, value] of Object.entries(person)) {
    console.log(key, value);
}

Kết quả:

Lưu ý:

  • for...in tự động duyệt qua các key.
  • for...of cần kết hợp Object.entries() để lấy cả key và value.

Khi nào nên sử dụng for...of thay vì for...in và forEach?

Sử dụng for...of khi:

Cần duyệt giá trị trong mảng (Array), chuỗi (String), tập hợp (Set), bản đồ (Map).
Muốn sử dụng break hoặc continue để kiểm soát vòng lặp.
Làm việc với async/await (for await...of).

Ví dụ: Dùng for...of với mảng

const numbers = [10, 20, 30];

for (let num of numbers) {
    console.log(num);
}
Kết quả:
10
20
30

Sử dụng for...in khi:

Cần duyệt qua key của Object hoặc index của mảng.

Không quan tâm đến giá trị mà chỉ cần lấy tên thuộc tính hoặc vị trí trong mảng.

Lưu ý: for...in không nên dùng với Array vì nó có thể duyệt qua cả thuộc tính kế thừa.\

Ví dụ: Dùng for...in với Object

const person = { name: "Alice", age: 25, city: "New York" };

for (let key in person) {
    console.log(key, person[key]);
}

Kết quả:

name Alice
age 25
city New York

Sử dụng forEach() khi:

Làm việc với mảng (Array), đặc biệt khi cần xử lý từng phần tử mà không cần dùng break hoặc continue.
Muốn sử dụng callback function để xử lý dữ liệu.

Lưu ý: forEach() không hỗ trợ break hoặc continue, nên nếu cần dừng vòng lặp giữa chừng, hãy dùng for...of.

Ví dụ: Dùng forEach() với mảng

const numbers = [10, 20, 30];

numbers.forEach(num => {
    console.log(num);
});

Kết quả:

10
20
30

Kết bài

Vòng lặp for...of là một công cụ mạnh mẽ trong JavaScript, giúp lập trình viên duyệt qua các phần tử của mảng (Array), chuỗi (String), tập hợp (Set), bản đồ (Map) một cách dễ dàng và hiệu quả. Với cú pháp đơn giản, dễ đọc và hỗ trợ các tính năng như break, continueasync/await, for...of là lựa chọn lý tưởng khi làm việc với dữ liệu dạng iterable.

Tuy nhiên, nó không thể sử dụng trực tiếp với Object, nên khi cần lặp qua các thuộc tính của đối tượng, chúng ta nên dùng for...in hoặc kết hợp với Object.keys(), Object.entries(). Ngoài ra, khi xử lý mảng mà không cần dừng sớm, forEach() cũng là một phương án thay thế tốt.

Bài viết liên quan

  • 2