JavaScript 迭代器详解:原理、协议与自定义实现

作者:拾光时间:2026-10-24 15:14:30浏览:106

本文深入解析 JavaScript 中的迭代器模式,阐述可迭代协议与迭代器协议的核心机制。通过解读 Symbol.iterator 和 next() 方法的返回值结构,说明如何使对象支持 for...of 循环。同时提供传统写法与生成器函数两种自定义迭代器的实现方案,帮助开发者掌握 ES6 新增数据结构的遍历原理。

简介

迭代器是一种设计模式,旨在遍历链表、数组等容器对象,而无需暴露其内存分配的具体实现细节。通俗而言,它类似于一个移动指针,能够按顺序逐个获取数据,并明确指示遍历何时结束。获取数据后,即可执行后续所需的操作。

js 中的迭代器是什么样子的

在 JavaScript 中,迭代器是一个包含 next() 方法的特殊对象。每次调用 next() 都会返回一个结果对象,该对象包含两个属性:value 表示下一个待返回的值,done 为布尔值,若已迭代至序列末尾则设为 true。迭代器内部维护一个指针,指向当前集合中的位置,每调用一次 next() 即返回下一个可用值,其结构大致如下。


{
  next: function () {
        return {
            value:'',
            done: true / false
        }  
    }
} 

迭代协议

随着 JavaScript 语言能力的增强,Map、Set、WeakMap 等新数据类型相继出现。为了实现对这些不同数据结构的统一迭代,ES6 引入了迭代协议。

迭代协议并非新的内置实现或语法,而是一种约定。任何遵循特定约定的对象均可实现这些协议。

迭代协议具体包含两个部分:可迭代协议和迭代器协议。

简单来说,在 JavaScript 中,任何满足迭代协议的对象均可被遍历。

可迭代协议

要使一个对象成为可迭代对象,必须实现 @@iterator 方法。这意味着该对象(或其原型链上的某个对象)必须拥有一个键为 @@iterator 的属性,该属性可通过常量 Symbol.iterator 访问。

简而言之,若希望某个对象可被遍历,则该对象必须拥有 @@iterator 属性,且可通过 Symbol.iterator 进行访问。

属性

值

[Symbol.iterator]

一个无参数的函数,其返回值为一个符合迭代器协议的对象。

迭代器协议

迭代器协议定义了产生一系列值(无论有限还是无限)的标准方式。当值为有限个时,所有值迭代完毕后,将返回一个默认返回值。

只有实现了具有特定语义的 next() 方法的对象,才符合迭代器协议。

属性

值

next

一个无参数函数,返回一个应当拥有以下两个属性的对象:

done(boolean)

next() 方法必须返回一个对象,该对象应当有两个属性: done 和 value,如果返回了一个非对象值(比如 false 或 undefined),则会抛出一个 异常("iterator.next() returned a non-object value")。

迭代过程

当需要对一个对象进行迭代(例如在 for...of 循环中使用时),首先会不带参数调用其 @@iterator 方法(此时返回一个结构为 { next: function() {} } 的对象),随后通过该方法返回的迭代器不断调用 next() 方法来获取要迭代的值。

迭代总结

迭代协议可总结为:一个对象若要被遍历,必须同时满足可迭代协议和迭代器协议。

  • 可迭代协议:该对象必须拥有 @@iterator 属性,可通过 Symbol.iterator 访问。
  • 迭代器协议:这是一个对象,其 next() 函数返回一个包含 value 和 done(布尔值,指示是否为最后一个元素,done 为 true 时 value 可省略)两个属性的对象。

也就是说,迭代器对象本质上是一个指针对象。通过调用该指针对象的 next() 方法来移动指针。

自定义迭代

普通对象未实现迭代器,因此无法直接遍历。为了实现对象的遍历,需要在对象上实现前述的迭代器。通常有两种写法:一种是传统写法,需自行控制内部状态;另一种是利用生成器函数返回的 Generator 迭代器来实现,代码如下。

传统写法


let obj = {
  name: 'joel',
  adress: 'gz',
  [Symbol.iterator]: () => {
     // 这里不要用this, 因为是return fn, this 会丢失
    let index = -1, atrrList = Object.keys(obj);
    const objIterator = {
      next: () => {
        let result = ''
        index++
        if (index < atrrList.length) {
          result = {
            value: atrrList[index],
            done: false
          }
        } else {
          result = {
            done: true
          }
        }
        return result
      }
    }
    return objIterator
  }
}

for (const item of obj) {
    console.log('atrrs:' + item + ',value:' + obj[item])
}

生成器函数写法


// 为不可迭代的对象添加迭代器
let obj = {
  a: 1,
  b: 2
}
obj[Symbol.iterator] = function* () {
  let keys = Object.keys(obj);
  //取到key值的长度
  let len = keys.length;
  //定义循环变量
  let n = 0;
  //条件判断
  while (n <= len - 1) {
      yield { k: keys[n], v: obj[keys[n]] };
      n++
  }
}
//返回的是个对象的key和value
for (let { k, v } of obj) {
  console.log(k, v);
}

其他相关内容,如内置可迭代对象、用于可迭代对象的语法、接受可迭代对象的内置 API 等,请点击 这里

到此这篇关于学会javascript之迭代器的文章就介绍到这了,更多相关javascript 迭代器内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

作者最新文章