0

0

JS如何实现迭代协议?可迭代对象

小老鼠

小老鼠

发布时间:2025-08-23 11:54:02

|

398人浏览过

|

来源于php中文网

原创

JavaScript迭代协议通过Symbol.iterator让对象可迭代,实现该方法并返回带next()的迭代器对象,即可用for...of或展开运算符遍历;生成器函数(function*)配合yield能更简洁地创建迭代器,自动管理状态与next()逻辑,提升代码可读性与灵活性。

js如何实现迭代协议?可迭代对象

JavaScript中的迭代协议,说白了,就是一套约定,它让任何对象都能定义自己的遍历行为。核心在于实现一个特定的方法:

[Symbol.iterator]
。只要一个对象有这个方法,并且这个方法能返回一个符合迭代器协议的对象,那它就是“可迭代对象”。这意味着你可以用
for...of
循环它,或者用展开运算符(
...
)来解构它,就像处理数组一样。这套机制让数据消费变得非常统一和灵活。

迭代协议的实现机制

要让一个JavaScript对象变得可迭代,你需要给它添加一个名为

[Symbol.iterator]
的方法。这个方法必须是一个函数,并且它被调用时,必须返回一个“迭代器”对象。

那么,什么是迭代器呢?迭代器本身也是一个对象,它必须包含一个

next()
方法。每次调用这个
next()
方法时,它都应该返回一个包含两个属性的对象:

  • value
    : 这是当前迭代到的值。
  • done
    : 这是一个布尔值,表示迭代是否已经完成。如果迭代结束,
    done
    就应该是
    true
    ;否则,就是
    false

举个例子,假设我们想创建一个简单的计数器,让它能从某个数字开始,数到另一个数字:

function createCounter(start, end) {
  let current = start;
  return {
    [Symbol.iterator]() { // 这就是可迭代协议的关键
      return { // 返回一个迭代器对象
        next() { // 迭代器对象必须有next方法
          if (current <= end) {
            return { value: current++, done: false };
          } else {
            return { value: undefined, done: true };
          }
        }
      };
    }
  };
}

const myCounter = createCounter(1, 3);

for (const num of myCounter) {
  console.log(num); // 输出 1, 2, 3
}

// 也可以用展开运算符
const numsArray = [...createCounter(5, 7)];
console.log(numsArray); // 输出 [5, 6, 7]

这里可以看到,

createCounter
返回的对象就是可迭代的,因为它实现了
[Symbol.iterator]
。而
[Symbol.iterator]
方法返回的那个带有
next()
的对象,就是迭代器。这种分离的设计很常见,让你可以控制迭代的状态。

for...of
循环是如何与迭代协议协同工作的?

for...of
循环是ES6引入的,它专门用来遍历可迭代对象。它的工作原理其实非常直接,但又很巧妙。当你写下
for (const item of someIterableObject)
时,JavaScript引擎在幕后做了几件事:

它会首先尝试调用

someIterableObject
[Symbol.iterator]()
方法。如果这个方法不存在,或者返回的不是一个迭代器对象,那么就会抛出一个错误,告诉你这个对象不是可迭代的。

SCA介绍及应用实例 中文WORD版
SCA介绍及应用实例 中文WORD版

本文档主要讲述的是SCA介绍及应用实例;SCA(Service Component Architecture)是针对SOA提出的一套服务体系构建框架协议,内部既融合了IOC的思想,同时又把面向对象的复用由代码复用上升到了业务模块组件复用,同时将服务接口,实现,部署,调用完全分离,通过配置的形式灵活的组装,绑定。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看

下载

如果成功获取到迭代器,

for...of
就会反复调用这个迭代器的
next()
方法。每次调用,它都会检查
next()
返回的对象中的
done
属性。

  • 如果
    done
    false
    ,那么
    value
    属性的值就会被赋给
    item
    变量,然后循环体内的代码会被执行。
  • 如果
    done
    true
    ,这意味着迭代已经完成,
    for...of
    循环就会终止。

这与传统的

for...in
循环形成鲜明对比。
for...in
是用来遍历对象属性名的,它会枚举对象自身以及原型链上的可枚举属性。而
for...of
则完全聚焦于数据集合的“值”本身,它不关心属性名,只关心通过迭代协议暴露出来的数据序列。这使得
for...of
在处理数组、字符串、Map、Set以及你自定义的任何可迭代数据结构时,都能提供一种统一且直观的遍历方式。在我看来,这是现代JavaScript中处理数据流非常基础且强大的一个抽象。

如何利用生成器函数更简洁地创建可迭代对象?

手动实现迭代器的

next()
方法,尤其是当迭代逻辑比较复杂时,可能会显得有些冗长和容易出错。JavaScript为此提供了一个语法糖,也就是“生成器函数”(Generator Function),它能极大地简化可迭代对象的创建过程。

生成器函数使用

function*
语法定义,并且在函数体内部,你可以使用
yield
关键字来“产出”值。每次
yield
一个值,生成器函数就会暂停执行,并返回这个值作为迭代器结果的
value
,同时
done
会被自动设为
false
。当再次调用迭代器的
next()
方法时,生成器函数会从上次暂停的地方继续执行,直到遇到下一个
yield
或函数结束。如果函数执行完毕(没有更多的
yield
),那么返回的
done
就会是
true

这意味着,一个生成器函数本身在被调用时,就会返回一个迭代器对象,这个对象已经自动实现了

next()
方法。所以,要创建一个可迭代对象,你只需要让它的
[Symbol.iterator]
方法是一个生成器函数即可。

// 还是那个计数器,用生成器函数实现
function createCounterWithGenerator(start, end) {
  return {
    [Symbol.iterator]: function* () { // [Symbol.iterator] 现在是一个生成器函数
      for (let i = start; i <= end; i++) {
        yield i; // 每次yield一个值,就会暂停并返回
      }
    }
  };
}

const myGenCounter = createCounterWithGenerator(10, 12);

for (const num of myGenCounter) {
  console.log(num); // 输出 10, 11, 12
}

// 或者更直接地,生成器函数本身就是迭代器
function* simpleGenerator() {
  yield 'Hello';
  yield 'World';
  yield '!';
}

const gen = simpleGenerator(); // 调用生成器函数直接返回一个迭代器
console.log(gen.next()); // { value: 'Hello', done: false }
console.log(gen.next()); // { value: 'World', done: false }
console.log(gen.next()); // { value: '!', done: false }
console.log(gen.next()); // { value: undefined, done: true }

// 甚至可以直接用for...of遍历生成器函数返回的迭代器
for (const item of simpleGenerator()) {
    console.log(item); // 输出 Hello, World, !
}

在我看来,生成器函数简直是迭代器协议的“最佳拍档”。它把复杂的迭代逻辑,特别是那些需要维护内部状态的遍历,用一种更接近同步代码的直观方式表达出来。你不再需要手动管理

value
done
yield
关键字和生成器函数的执行流程帮你把这些都处理好了。这不仅提升了代码的可读性,也大大降低了实现自定义迭代器的心智负担。当你需要处理任何形式的数据流,无论是从文件读取、网络请求分块,还是简单的数字序列,生成器函数都能提供一种非常优雅的解决方案。

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

553

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

374

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

731

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

477

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

394

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

990

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

656

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

551

2023.09.20

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

61

2026.01.14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.2万人学习

ECMAScript6 / ES6---十天技能课堂
ECMAScript6 / ES6---十天技能课堂

共25课时 | 1.9万人学习

PHP自制框架
PHP自制框架

共8课时 | 0.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号