Trong JavaScript, for...in và for...of là hai cấu trúc vòng lặp khác nhau với mục đích và trường hợp sử dụng rõ ràng:
1. Vòng lặp for...in
- Mục đích: Duyệt qua các thuộc tính có thể đếm được của một đối tượng (bao gồm cả thuộc tính kế thừa).
- Đối tượng áp dụng: Các đối tượng thông thường (
Object). - Đặc điểm:
- Trả về tên khóa (key) của thuộc tính.
- Có thể duyệt các thuộc tính từ chuỗi nguyên mẫu nếu không được lọc bằng
hasOwnProperty. - Không đảm bảo thứ tự duyệt (đặc biệt với các khóa số, có thể được sắp xếp theo giá trị số).
const obj = { a: 1, b: 2 };
for (const key in obj) {
console.log(key); // In ra 'a', 'b'
}
// Mảng (không khuyến khích)
const arr = [10, 20, 30];
arr.foo = "bar";
for (const index in arr) {
console.log(index); // In ra '0', '1', '2', 'foo'
}
2. Vòng lặp for...of
- Mục đích: Duyệt qua các giá trị của các đối tượng có thể lặp.
- Đối tượng áp dụng: Mảng, chuỗi,
Map,Set,arguments,NodeListvà các đối tượng thực hiện giao diện[Symbol.iterator]. - Đặc điểm:
- Trả về trực tiếp giá trị (value) của phần tử.
- Không duyệt các thuộc tính không phải chỉ số do người dùng thêm vào.
- Không thể dùng trực tiếp với đối tượng thông thường (cần triển khai iterator thủ công).
const arr = [10, 20, 30];
arr.foo = "bar";
for (const value of arr) {
console.log(value); // In ra 10, 20, 30 (bỏ qua foo)
}
const str = "hello";
for (const char of str) {
console.log(char); // In ra 'h', 'e', 'l', 'l', 'o'
}
// Ví dụ với Map
const map = new Map([["a", 1], ["b", 2]]);
for (const [key, value] of map) {
console.log(key, value); // In ra 'a 1', 'b 2'
}
Tổng kết so sánh
| Thuộc tính | for...in |
for...of |
|---|---|---|
| Nội dung duyệt | Tên khóa (key) của đối tượng | Giá trị (value) của phần tử |
| Đối tượng hỗ trợ | Đối tượng thông thường | Mảng, chuỗi, Map, Set... |
| Thuộc tính từ nguyên mẫu | Có thể duyệt (cần lọc) | Không liên quan |
| Thuộc tính tùy chỉnh | Duyệt tất cả thuộc tính có thể đếm | Chỉ duyệt giá trị phần tử, bỏ qua thuộc tính không phải chỉ số |
| Hỗ trợ đối tượng thông thường | Có | Không mặc định (cần iterator riêng) |
Khi nào nên sử dụng?
- Sử dụng
for...inđể xử lý thuộc tính của đối tượng. - Sử dụng
for...ofđể lấy giá trị từ các đối tượng có thể lặp như mảng hay chuỗi. - Tránh dùng
for...incho mảng vì có thể gặp các thuộc tính không mong muốn.
Nếu cần lặp qua các giá trị của đối tượng thông thường, có thể lấy danh sách khóa trước:
const obj = { a: 1, b: 2 };
for (const key of Object.keys(obj)) {
console.log(obj[key]); // In ra 1, 2
}