什么是javascript迭代器_for_of循环如何遍历可迭代对象【教程】

13次阅读

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

什么是javascript迭代器_for_of循环如何遍历可迭代对象【教程】

for-of 循环只能遍历实现了 [Symbol.iterator] 的对象

不是所有 js 对象都能用 for...of 遍历。它只认「可迭代对象(iterable)」——即内部有 [Symbol.iterator] 方法、且该方法返回一个符合迭代器协议的对象。数组、StringMapSetTypedArrayargumentsnodeList 是原生可迭代的;普通对象({})默认不是。

常见错误:直接对 plain object 写 for...of,会报 TypeError: xxx is not iterable

  • 想遍历对象键值?用 Object.keys(obj)Object.entries(obj) 包一层再 for-of
  • 自定义类要支持 for-of?必须在原型上部署 [Symbol.iterator] 方法
  • Node.js 早期版本(Map.prototype.values() 返回值)可能不被 for-of 直接识别,需确认运行时环境

for...offor...in 的根本区别在哪

for...in 遍历的是对象的**可枚举属性名(字符串 key)**,包括原型链上的;for...of 遍历的是对象的**迭代值(value)**,只走自身实现的迭代协议,与属性名无关。

典型陷阱:for...in 遍历数组会得到索引字符串("0", "1"),还可能混入添加的非数字属性;而 for...of 拿到的是真实元素值(arr[0], arr[1]),更安全直观。

立即学习Java免费学习笔记(深入)”;

  • for...in 适合查对象结构(比如调试时看有哪些字段)
  • for...of 适合取数据(尤其配合 break/continueawait 使用)
  • 两者都不能保证遍历顺序对所有对象一致,但对数组、字符串、Map、Set,ES2015+ 规范已明确要求按插入顺序

如何让自定义对象支持 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() 的对象
  • node.js 中检查是否启用了 --harmony-iterator(v12 以前旧版本需要)
  • 使用 Babel 编译时,确保 @babel/preset-env 配置了目标环境,否则可能把 for...of 转成不兼容的代码
  • 某些库(如早期 Lodash)的包装对象(_.wrap() 等)不自动继承迭代器,需显式调用 .value() 获取底层数组再遍历

迭代器协议看着抽象,实际就是「提供一个标准接口让 for-of 知道怎么一步步取值」。真正容易卡住的地方,往往不是写错语法,而是没意识到某个对象根本没实现这个接口,或者环境不支持。

text=ZqhQzanResources