可通过计算属性名将Symbol.iterator作为动态键为对象添加自定义迭代行为,使其支持for...of、扩展运算符、解构等;生成器函数可简化实现;可用typeof obj[Symbol.iterator]===‘function’等方法验证。

可以通过计算属性名将 Symbol.iterator 作为动态键,为对象添加自定义迭代行为,使其能被 for...of、扩展运算符([...obj])、解构等语法消费。
计算属性名声明迭代器方法
ES6 允许用方括号 [] 包裹表达式来定义属性名。把 Symbol.iterator 放在方括号中,就能让对象拥有标准的迭代接口:
示例:
const myIterable = {
data: ['a', 'b', 'c'],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.data.length) {
return { value: this.data[index++], done: false };
}
return { value: undefined, done: true };
}
};
}
};
// 现在可以正常迭代
for (const item of myIterable) {
console.log(item); // 'a', 'b', 'c'
}
返回符合迭代协议的对象
Symbol.iterator 方法必须返回一个“迭代器对象”,该对象需有 next() 方法,且每次调用返回形如 { value, done } 的对象。注意几点:
-
闭包保存状态:如上例中用
let index = 0在闭包中维护遍历位置,避免多次调用for...of时互相干扰 -
不要复用 this:迭代器内部的
this指向原对象,但next()是独立函数,若直接访问this.data需确保绑定正确;更稳妥的做法是把数据提前捕获进闭包 -
支持多次迭代:每次调用
[Symbol.iterator]()都应返回**新**的迭代器,否则多个for...of循环会共享状态、互相影响
结合类与私有状态封装可迭代类
用 class 封装更清晰,配合私有字段(或闭包)管理状态:
class Countdown {
constructor(from) {
this.from = from;
}
*[Symbol.iterator]() {
let i = this.from;
while (i > 0) yield i--;
}
}
const count = new Countdown(3);
console.log([...count]); // [3, 2, 1]
这里用了生成器函数(function*),它天然返回符合协议的迭代器,写法更简洁,也自动处理了状态隔离。
验证是否真正可迭代
可通过以下方式快速检测:
typeof obj[Symbol.iterator] === 'function'-
Array.from(obj)不抛错且返回预期数组 -
[...obj]能展开成值列表 -
for (const x of obj) {}可执行循环体

















