要让自定义类支持展开和for...of,必须实现[Symbol.iterator]方法并返回符合迭代器协议的对象:即具有next()方法,返回{value, done}格式对象;推荐用function*生成器函数实现,可自动满足协议。
![javascript中怎么给自定义的类添加[symbol.iterator]方法使其能被展开](https://img.php.cn/upload/article/001/242/473/178486800192782.png)
要让自定义类支持展开(比如用 ... 操作符或 for...of 循环),必须实现 [Symbol.iterator] 方法,且该方法需返回一个符合迭代器协议的对象——即带有 next() 方法,并返回形如 { value, done } 的对象。
1. 基本写法:返回一个生成器函数
最简洁、推荐的方式是用 function* 生成器函数作为 [Symbol.iterator] 的值。生成器自动满足迭代器协议,无需手动实现 next。
class MyList {
constructor(items) {
this.items = items || [];
}
*[Symbol.iterator]() {
for (const item of this.items) {
yield item;
}
}
}
// 使用示例
const list = new MyList([1, 2, 3]);
console.log([...list]); // [1, 2, 3]
for (const x of list) console.log(x); // 1, 2, 3
2. 手动实现迭代器对象(不推荐但需理解)
如果不用生成器,可以显式返回一个带 next() 方法的对象。注意要维护内部状态(如当前索引),确保每次调用 next() 返回正确的 value 和 done。
- 每次调用
next()应返回{ value: ..., done: true|false } -
done: true表示迭代结束,之后的调用也应返回{ value: undefined, done: true } - 通常需要闭包或实例属性保存状态(如索引),避免多次调用
[Symbol.iterator]()互相干扰
class MyList {
constructor(items) {
this.items = items || [];
}
[Symbol.iterator]() {
let index = 0;
const items = this.items;
return {
next() {
if (index < items.length) {
return { value: items[index++], done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
}
3. 注意事项和常见坑
-
[Symbol.iterator]必须是**方法**(函数),不能是普通属性或箭头函数(箭头函数无法正确绑定this,且无法用yield) - 生成器函数中
this指向类实例,可安全访问实例属性(如this.items) - 若类需支持多次遍历(如多次展开),生成器天然支持;手动实现时,每次调用
[Symbol.iterator]()都应返回**新**的迭代器对象,避免状态复用 - 不要在
[Symbol.iterator]内直接返回数组(如return this.items[Symbol.iterator]();),这会丢失this绑定,导致报错
4. 实际扩展:支持异步迭代(可选)
如果数据源是异步的(如从 API 加载),可用 [Symbol.asyncIterator],配合 async function* 和 for await...of。但这与展开运算符无关(... 不支持异步迭代)。
立即学习“Java免费学习笔记(深入)”;
class AsyncList {
constructor(promiseItems) {
this.promiseItems = promiseItems;
}
async *[Symbol.asyncIterator]() {
const items = await this.promiseItems;
for (const item of items) yield item;
}
}
// 只能用于 for await...of,不能 [...asyncList]
不复杂但容易忽略细节:只要 [Symbol.iterator] 返回合法迭代器,就能被所有迭代上下文(展开、for...of、Array.from、解构等)识别。优先用生成器,清晰又可靠。


















