JavaScript迭代器和可迭代协议使对象支持for...of等语法;可迭代对象需实现[Symbol.iterator]方法返回迭代器,迭代器必须有返回{value,done}的next()方法。

JavaScript 的迭代器(Iterator)和可迭代协议(Iterable Protocol)是一套让对象支持 for...of、展开运算符([...obj])、解构等语法的机制。核心在于:可迭代对象必须实现 [Symbol.iterator] 方法,该方法返回一个符合迭代器协议的对象;而迭代器对象必须有 next() 方法,每次调用返回 { value, done } 形式的对象。
迭代器协议:定义“怎么一步步取值”
一个对象是迭代器,当且仅当它有 next() 方法,且该方法返回形如 { value: any, done: boolean } 的对象。done: true 表示遍历结束,之后的调用应始终返回 { value: undefined, done: true }。
例如,手动创建一个简单迭代器:
const counter = {
[Symbol.iterator]() {
let i = 0;
return {
next() {
if (i < 3) {
return { value: i++, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
for (const n of counter) console.log(n); // 0, 1, 2
可迭代协议:定义“谁可以被 for...of 遍历”
一个对象是可迭代的,当且仅当它实现了 [Symbol.iterator] 方法(即具有该 key 的函数),且该函数返回一个迭代器对象。
- 内置类型如
Array、String、Map、Set、TypedArray都默认可迭代 -
Object默认不可迭代(没有[Symbol.iterator]),所以for...of {}会报错 - 只要为任意对象添加合法的
[Symbol.iterator]方法,它就变成可迭代对象
让自定义类/对象可迭代:两种常用方式
方式一:在类原型上部署 [Symbol.iterator] 方法(推荐)
立即学习“Java免费学习笔记(深入)”;
class Countdown {
constructor(start) {
this.start = start;
}
*[Symbol.iterator]() {
for (let i = this.start; i > 0; i--) {
yield i;
}
}
}
for (const n of new Countdown(3)) console.log(n); // 3, 2, 1
console.log([...new Countdown(2)]); // [2, 1]
注意:使用生成器函数(function* 或简写 *[Symbol.iterator]())最简洁,它自动返回符合协议的迭代器。
方式二:直接在实例上设置 [Symbol.iterator](适合简单对象)
const range = {
from: 1,
to: 3,
[Symbol.iterator]() {
let current = this.from;
return {
next: () => {
if (current <= this.to) {
return { value: current++, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
console.log([...range]); // [1, 2, 3]
注意事项与常见陷阱
-
[Symbol.iterator]必须是函数,不能是箭头函数(箭头函数无法访问this) - 每次
for...of都会调用[Symbol.iterator]()获取新迭代器,所以多次遍历互不影响 - 如果想让对象既可迭代又保持状态(如单次消费),需确保
next()内部逻辑正确维护状态 - 生成器函数天然满足迭代器协议,是实现可迭代对象最安全、最简洁的方式











