javascript迭代器是什么_如何让对象可迭代?

11次阅读

javaScript迭代器是明确协议而非语法糖;对象需实现[symbol.iterator]方法返回符合{value, done}结构的迭代器对象,ArrayString等原生类型已实现该协议。

javascript迭代器是什么_如何让对象可迭代?

javascript 迭代器不是语法糖,而是明确的协议约定;让对象可迭代的关键,是给它加上 [Symbol.iterator] 方法,且该方法必须返回一个符合迭代器协议的对象。

什么是迭代器协议?

迭代器协议规定:一个对象只要拥有 next() 方法,且该方法返回形如 { value: any, done: Boolean } 的对象,就称为“迭代器对象”。它不关心怎么生成值,只保证每次调用 next() 都返回下一个状态。

而“可迭代对象”是另一层协议:该对象必须有 [Symbol.iterator] 属性,其值是一个无参函数,调用后返回一个迭代器对象。

  • ArrayStringmap 等原生类型都实现了这个协议
  • for...of...spreadArray.from() 等语法/方法内部会自动调用 [Symbol.iterator]
  • 如果对象没有 [Symbol.iterator]for...of 会直接报错:TypeError: xxx is not iterable

手动实现一个可迭代对象

最简方式:在对象上定义 [Symbol.iterator] 方法,返回一个闭包封装的迭代器。

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

const counter = {   from: 1,   to: 3,   [Symbol.iterator]() {     let current = this.from;     const { to } = this;     return {       next() {         if (current <= to) {           return { value: current++, done: false };         }         return { value: undefined, done: true };       }     };   } };  for (const num of counter) {   console.log(num); // 1, 2, 3 }

注意点:

  • 不能写成箭头函数——this 会丢失,无法访问 from/to
  • 每次调用 [Symbol.iterator] 应返回**新迭代器**,否则多次 for...of 会互相干扰
  • done: true 后,后续调用 next() 仍应返回 { value: undefined, done: true }(规范要求)

用生成器函数简化实现

生成器函数(function*)天然返回符合协议的迭代器,是实现可迭代对象最简洁的方式。

const range = {   from: 10,   to: 12,   *[Symbol.iterator]() {     for (let i = this.from; i <= this.to; i++) {       yield i;     }   } };  console.log([...range]); // [10, 11, 12] console.log(Array.from(range)); // [10, 11, 12]

优势明显:

  • 自动管理内部状态(无需手动维护 current
  • 逻辑清晰,yield 直观表达“产出一个值”
  • 支持异步生成器(async function*),可用于流式数据处理

但要注意:生成器函数体内不能使用 this 指向外层对象(除非显式绑定),常见写法是提前解构或传参。

常见错误和兼容性提醒

实际开发中容易忽略的几个点:

  • 忘记方括号语法:Symbol.iterator 必须用 [Symbol.iterator] 作为属性名,写成 Symbol.iterator()字符串 "Symbol.iterator" 都无效
  • Node.js 早期版本(Symbol,需用 Babel 转译或改用其他遍历方案(如提供 forEach 方法)
  • 自定义迭代器若抛出异常,for...of 会中断并把错误向上冒泡,务必确保 next() 内部健壮
  • 如果对象已有 [Symbol.iterator] 但返回非对象(如 null 或数字),也会触发 is not iterable 错误

真正难的不是写出来,而是想清楚:这个对象“按什么顺序、产什么值、何时结束”——协议只是外壳,语义才是核心。

text=ZqhQzanResources