for-of循环仅适用于实现了[Symbol.iterator]方法的可迭代对象;数组、字符串、Map等原生可迭代,普通对象默认不可迭代,需用Object.keys()等转换或手动部署[Symbol.iterator]。
[Symbol.iterator] 的对象不是所有

for...of 遍历。它只认「可迭代对象(iterable)」——即内部有 [Symbol.iterator] 方法、且该方法返回一个符合迭代器协议的对象。数组、String、Map、Set、TypedArray、arguments、NodeList 是原生可迭代的;普通对象({})默认不是。
常见错误:直接对 plain object 写 for...of,会报 TypeError: xxx is not iterable。
Object.keys(obj)、Object.entries(obj) 包一层再 for-of[Symbol.iterator] 方法for...of 和 for...in 的根本区别在哪for...in 遍历的是对象的**可枚举属性名(字符串 key)**,包括原型链上的;for...of 遍历的是对象的**迭代值(value)**,只走自身实现的迭代协议,与属性名无关。
典型陷阱:for...in 遍历数组会得到索引字符串("0", "1"),还可能混入添加的非数字属性;而 for...of 拿到的是真实元素值(arr[0], arr[1]),更安全直观。
for...in 适合查对象结构(比如调试时看有哪些字段)for...of 适合取数据(尤其配合 break/continue 或 await 使用)for...of
只需在对象(或其原型)上定义 [Symbol.iterator] 方法,返回一个对象,该对象有 next() 方法,每次调用返回 { value, done } 形式的迭代结果。
const counter = {
from: 1,
to: 3,
[Symbol.iterator]() {
let current = this.from;
const last = this.to;
return {
next() {
if (current <= last) {
return { value: current++, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (const num of counter) {
console.log(num); // 1, 2, 3
}
next() 必须是无参函数;带参数会被忽略(除非是 generator,但那是另一套机制)done: true 后,后续调用 next() 应始终返回 { value: undefined, done: true }
TypeError: xxx is not a function 怎么排查这个错误常出现在你误以为某个对象可迭代,但它返回的 [Symbol.iterator] 是 undefined 或非函数。例如:DOM 元素集合在低版本浏览器中可能没正确暴露迭代器;或你手动删了 Array.prototype[Symbol.iterator](极少见但可能)。
快速验证方式:
const obj = /* 你的对象 */; console.log(typeof obj[Symbol.iterator]); // 应该是 "function" console.log(obj[Symbol.iterator]()); // 应该返回一个有 next() 的对象
--harmony-iterator(v12 以前旧版本需要)@babel/preset-env 配置了目标环境,否则可能把 for...of 转成不兼容的代码_.wrap() 等)不自动继承迭代器,需显式调用 .value() 获取底层数组再遍历迭代器协议看着抽象,实际就是「提供一个标准接口让 for-of 知道怎么一步步取值」。真正容易卡住的地方,往往不是写错语法,而是没意识到某个对象根本没实现这个接口,或者环境不支持。