普通对象默认不可被for...of遍历,因其缺少symbol.iterator方法;判断依据是obj[symbol.iterator]为函数且调用后返回含value和done属性的next()对象;需手动部署该方法以支持迭代。

普通对象默认不可被 for...of 遍历,因为它没有 Symbol.iterator 方法。识别和部署的关键在于:**检查对象是否拥有可调用的 [Symbol.iterator] 属性,且该属性返回一个符合迭代器协议的对象(即具有 next() 方法,返回 { value, done } 形式的结果)**。
怎么判断对象已有 Symbol.iterator
直接在控制台或代码中检测:
-
查属性是否存在:
obj[Symbol.iterator]不为undefined且是函数 -
试调用是否合法:
typeof obj[Symbol.iterator] === 'function' -
验证返回值结构:
const iter = obj[Symbol.iterator](); iter.next()应返回带value和done的对象
为什么普通对象需要手动部署
JavaScript 规定只有原生可遍历结构(如数组、字符串、Map、Set)自带 Symbol.iterator。普通对象(字面量或构造函数实例)不自动提供,因为它的属性无序、语义上不是“序列”。但若你希望它能被 for...of 按键名/键值遍历,就必须显式添加。
部署的两种主流方式
方式一:手写迭代器对象(适合控制细节)
- 在对象自身或原型上定义
[Symbol.iterator]()方法 - 方法内部维护索引(如
let i = 0),返回一个含next()的对象 -
next()根据当前状态返回{ value: ..., done: false/true }
方式二:用 Generator 函数(更简洁、自动管理状态)
- 直接让
[Symbol.iterator]是一个function* - 用
yield逐个产出值,引擎自动封装成标准迭代器 - 例如:
[Symbol.iterator]: function* () { for (let key of Object.keys(this)) yield { [key]: this[key] }; }
常见错误提醒
部署后仍报错“is not iterable”,多数因以下原因:
- 把
Symbol.iterator赋值给了非函数值(比如直接赋了个数组) - 对象是类数组(有
length和数字键),却错误复用Array.prototype[Symbol.iterator]—— 这只对真正类数组有效,对{a:1, b:2}无效 - 在原型链上部署时,覆盖了已有方法,或部署位置不对(如挂在实例而非
prototype或Object.prototype) -
next()返回对象缺少done属性,或类型不是布尔值










