可利用计算属性名动态定义[symbol.iterator]()方法,使对象成为可迭代对象,支持for...of、扩展运算符等;它返回一个含next()方法的对象,next()返回{value, done}结构,symbol.iterator是内置symbol,用于指定默认迭代器工厂函数。

可以利用计算属性名动态定义 [Symbol.iterator] 方法,让对象具备原生迭代能力,从而被 for...of、扩展运算符、解构等语法直接消费。
1. 理解 Symbol.iterator 是什么
Symbol.iterator 是一个内置的全局 symbol,用于指定对象的默认迭代器方法。当对象实现了该方法并返回一个符合迭代器协议的对象(即有 next() 方法,返回 { value, done } 形式的对象),它就成为“可迭代对象”(iterable)。
注意:实现 [Symbol.iterator] 不等于实现迭代器本身,而是提供一个能生成迭代器的工厂函数。
2. 用计算属性名挂载迭代器方法
ES6 允许使用方括号语法定义动态属性名,Symbol.iterator 正好适合这种方式:
✅ 正确写法(推荐):
const stream = {
data: [10, 20, 30],
index: 0,
// 使用计算属性名绑定迭代器方法
[Symbol.iterator]() {
return {
next: () => {
if (this.index
<p><font color="red">⚠️ 常见错误(不生效):</font></p>
- 写成字符串
"Symbol.iterator"—— 这只是普通字符串属性,不是 symbol 键; - 在对象字面量中漏掉
[],如Symbol.iterator() {...}—— 会被当作方法名字面量,而非计算属性; - 把
next写在对象顶层,未包裹在[Symbol.iterator]()返回值中 —— 违反迭代器协议。
3. 支持多次迭代与状态隔离
上面例子中,this.index 存在共享状态问题:多次 for...of 会互相干扰。更健壮的做法是把迭代状态移到迭代器内部:
const stream = {
data: [10, 20, 30],
[Symbol.iterator]() {
let index = 0; // ✅ 每次调用都新建闭包状态
return {
next: () => {
if (index
<p>这样每次 <code>for...of</code> 都获得独立的迭代器实例,互不影响。</p>
<h3>4. 实现更实用的流式行为(如无限序列、异步流模拟)</h3>
<p>计算属性名 + <code>Symbol.iterator</code> 的组合非常灵活。例如,构建一个“偶数流”:</p>
<pre class="brush:php;toolbar:false;">const evenStream = {
[Symbol.iterator]() {
let n = 0;
return {
next() {
n += 2;
return { value: n, done: false }; // 无限迭代(需手动 break)
}
};
}
};
// 使用
for (const v of evenStream) {
if (v > 10) break;
console.log(v); // 2, 4, 6, 8, 10
}
若需支持异步迭代(for await...of),则应实现 [Symbol.asyncIterator],那是另一套协议,不与 Symbol.iterator 混用。











