Object thường không iterable, nên for...of hay [...obj] ném TypeError.
Muốn dùng được, object phải có phương thức tại khoá Symbol.iterator trả về một iterator — object có next() trả { value, done }.
js
const range = {
from: 1,
to: 3,
[Symbol.iterator]() {
let current = this.from;
const last = this.to;
return {
next: () => current <= last
? { value: current++, done: false }
: { value: undefined, done: true },
};
},
};
[...range]; // [1, 2, 3]
for (const n of range) {} // 1, 2, 3Cách gọn hơn là dùng generator — generator tự tuân thủ protocol:
js
const range2 = { *[Symbol.iterator]() { yield 1; yield 2; yield 3; } };Protocol này là thứ đứng sau for...of, spread, destructuring mảng, Array.from, Promise.all, new Map(...). Đó cũng là lý do Map/Set/NodeList spread được còn object thì không.
Với dữ liệu bất đồng bộ dùng Symbol.asyncIterator và for await...of — hữu ích khi đọc stream hoặc phân trang API mà không giữ hết dữ liệu trong bộ nhớ.