javascript中自定义遍历流程的核心是实现迭代器协议:对象需有[symbol.iterator]方法,该方法返回含next()的对象,next()返回{value, done}结构。

JavaScript 中自定义遍历流程的核心是实现迭代器协议(Iterator Protocol)——让对象拥有可被 for...of、展开运算符([...obj])、解构等语法消费的能力。关键不是写个循环,而是返回一个符合规范的迭代器对象。
迭代器协议的两个必要条件
一个对象要支持自定义遍历,必须满足:
- 拥有一个名为
[Symbol.iterator]的方法(即 可迭代协议); - 该方法返回的对象必须实现 迭代器协议:有
next()方法,且每次调用返回形如{ value: any, done: boolean }的对象。
手写一个简单可迭代对象
比如想让一个自定义的范围类 Range 支持 for...of 遍历:
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}
[Symbol.iterator]() {
let current = this.start;
return {
next() {
if (current
<p>注意:<code>next</code> 方法里的 <code>this</code> 指向的是返回的迭代器对象(不是 <code>Range</code> 实例),所以上面代码会出错。正确写法需绑定上下文或用闭包:</p>
<pre class="brush:php;toolbar:false;">[Symbol.iterator]() {
let current = this.start;
const end = this.end;
return {
next() {
if (current
<p>这样就能用了:</p>
<pre class="brush:php;toolbar:false;">for (const n of new Range(1, 4)) {
console.log(n); // 1, 2, 3
}
用生成器函数简化实现
手动写 next() 容易出错且逻辑分散。更推荐用 function* 生成器函数——它天然返回符合迭代器协议的对象:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}
*[Symbol.iterator]() {
for (let i = this.start; i
<p>生成器内部自动维护状态,<code>yield</code> 对应 <code>value</code>,函数结束自动返回 <code>done: true</code>,语义清晰、不易出错。</p>
<h3>支持提前终止(可选但实用)</h3>
<p>如果遍历可能被 <code>break</code>、<code>return</code> 或异常中断,可以给迭代器添加 <code>return()</code> 方法,用于清理资源(如关闭连接、释放内存):</p>
<pre class="brush:php;toolbar:false;">*[Symbol.iterator]() {
let current = this.start;
try {
while (current
<p>或者显式实现 <code>return</code>:</p>
<pre class="brush:php;toolbar:false;">[Symbol.iterator]() {
let current = this.start;
const iterator = {
next() {
if (current
<p>当 <code>for...of</code> 中遇到 <code>break</code>,引擎会自动调用 <code>iterator.return()</code>(如果存在)。</p>
<h3>常见陷阱和注意事项</h3>
<p>自定义迭代器时容易忽略的细节:</p>
-
[Symbol.iterator]必须是**零参数函数**,不能带参数; - 每次调用
[Symbol.iterator]()应返回**新迭代器**,否则多次遍历会相互影响(比如数组的[Symbol.iterator]每次都返回独立迭代器); -
value在done: true时可省略,但若提供,应有意义(如最后的默认值); - 迭代器对象不必是“类实例”,普通对象 + 方法即可,但需确保
next()可重复调用且状态正确。
不复杂但容易忽略:协议本身很轻量,关键是理解 Symbol.iterator 是入口,next() 是契约。用好生成器,90% 的场景都能干净解决。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










