JavaScript的可迭代协议是对象需拥有[Symbol.iterator]方法并返回符合迭代器协议的对象;该方法必须为普通函数,返回含next()且返回{value,done}的对象。

JavaScript 的可迭代协议到底是什么?
可迭代协议不是语法糖,也不是新特性,而是 JavaScript 引擎识别“能被 for...of、Array.from()、展开运算符 [...obj] 等消费”的一套约定:对象必须有名为 [Symbol.iterator] 的方法,且该方法返回一个符合迭代器协议的对象(即有 next() 方法,返回 { value, done } 形状的对象)。
让普通对象支持 for...of 的最简写法
直接在对象上定义 [Symbol.iterator] 方法即可。注意:不能用箭头函数(会丢失 this 绑定),且返回值必须是迭代器对象。
const obj = {
a: 1,
b: 2,
c: 3,
[Symbol.iterator]() {
const keys = Object.keys(this);
let index = 0;
return {
next() {
if (index < keys.length) {
const key = keys[index++];
return { value: this[key], done: false };
}
return { value: undefined, done: true };
}.bind(this)
};
}
};
for (const val of obj) {
console.log(val); // 1, 2, 3
}
-
[Symbol.iterator]是固定键名,必须用方括号计算属性写法 - 迭代器内部的
next()必须返回{ value, done },done: true后不可再返回有效值 - 如果想遍历键名而非值,把
this[key]换成key即可
用生成器函数 function* 简化实现
手写 next() 容易出错,生成器函数自动满足迭代器协议,是最推荐的方式。
const obj = {
x: 10,
y: 20,
z: 30,
*[Symbol.iterator]() {
for (const key of Object.keys(this)) {
yield this[key];
}
}
};
console.log([...obj]); // [10, 20, 30]
console.log(Array.from(obj)); // [10, 20, 30]
- 生成器函数前必须加
*,且内部用yield返回每个值 - 生成器函数体内的
this指向调用对象,无需手动bind - 不支持 IE,但现代环境(Chrome/Firefox/Safari/Edge)全部支持
常见踩坑点:为什么 for...of 还是报错?
即使加了 [Symbol.iterator],仍可能失败,原因很具体:
立即学习“Java免费学习笔记(深入)”;
-
[Symbol.iterator]方法抛出异常(比如访问了undefined的属性)→ 直接TypeError: obj is not iterable - 返回的不是对象,或对象没有
next方法 → 同样报is not iterable - 在类实例中定义时,写成了实例属性(如
this[Symbol.iterator] = function(){...}),但没在构造函数里执行,导致原型链上无该方法 - 使用
Object.assign({}, obj)后,[Symbol.iterator]不会被复制(Symbol 属性默认不可枚举,Object.assign只拷贝可枚举自有属性)
调试时可直接检查:typeof obj[Symbol.iterator] 是否为 "function",再手动调用 obj[Symbol.iterator]().next() 看返回结构是否合规。











