ES6 迭代器 (`Iterator`)使用总结

Iterator(迭代器)是 ES6 引入的一种 接口 ,用于 顺序访问 可迭代对象ArraySetMapStringarguments、自定义对象等)。

Iterator(迭代器)的作用有三个:

  1. 为各种数据结构提供一个统一的、简便的访问接口
  2. 使数据结构的成员能够按某种次序排列
  3. ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费

1. 迭代器的基本概念

(1) 迭代器是什么?

  • 迭代器是一种 特殊对象 ,提供 next() 方法,每次调用都会返回:

    js 复制代码
    { value: 当前值, done: 是否完成 }
  • done: true 时,表示迭代结束。


Iterator 的遍历过程

javascript 复制代码
// Iterator 的遍历过程如下:
1. 创建一个指针对象,指向当前数据结构的起始位置
2. 第一次调用指针对象的 next 方法,可以将指针指向数据结构的第一个成员
3. 第二次调用指针对象的 next 方法,指针就指向数据结构的第二个成员
4. 不断调用指针对象的 next 方法,直到它指向数据结构的结束位置

// 每一次调用 next 方法,都会返回一个包含 value 和 done 两个属性的对象
{
  value: 当前成员的值,
  done: 布尔值,表示遍历是否结束
}

2. 生成迭代器

(1) 手动创建迭代器

js 复制代码
function createIterator(arr) {
  let index = 0;
  return {
    next: function () {
      return index < arr.length
        ? { value: arr[index++], done: false }
        : { value: undefined, done: true };
    }
  };
}

let iterator = createIterator(["a", "b", "c"]);
console.log(iterator.next()); // { value: 'a', done: false }
console.log(iterator.next()); // { value: 'b', done: false }
console.log(iterator.next()); // { value: 'c', done: false }
console.log(iterator.next()); // { value: undefined, done: true }

📌 每次 next() 调用,都会返回 value 并前进


(2) 使用 Symbol.iterator

所有 可迭代对象ArraySetMap 等)都有 默认的迭代器 ,可以用 Symbol.iterator 访问:

js 复制代码
let arr = ["x", "y", "z"];
let iterator = arr[Symbol.iterator]();

console.log(iterator.next()); // { value: 'x', done: false }
console.log(iterator.next()); // { value: 'y', done: false }
console.log(iterator.next()); // { value: 'z', done: false }
console.log(iterator.next()); // { value: undefined, done: true }

📌 数组、字符串、Set、Map 都有 Symbol.iterator,可直接迭代


(3) 自定义对象的迭代器

普通对象没有默认迭代器,需手动实现:

js 复制代码
let myObj = {
  data: [10, 20, 30],
  [Symbol.iterator]: function () {
    let index = 0;
    return {
      next: () => {
        return index < this.data.length
          ? { value: this.data[index++], done: false }
          : { value: undefined, done: true };
      }
    };
  }
};

let iter = myObj[Symbol.iterator]();
console.log(iter.next()); // { value: 10, done: false }
console.log(iter.next()); // { value: 20, done: false }
console.log(iter.next()); // { value: 30, done: false }
console.log(iter.next()); // { value: undefined, done: true }

📌 对象没有默认迭代器,需实现 Symbol.iterator 才能用 for...of


3. for...of 遍历迭代器

所有 实现 Symbol.iterator 的对象 ,都可以用 for...of 遍历:

js 复制代码
let arr = ["A", "B", "C"];

for (let char of arr) {
  console.log(char);
}
// A
// B
// C

📌 相比 forEach()for...of 可与 breakcontinue 配合使用


4. 可迭代对象

可以使用 for...ofSymbol.iterator 的对象

  • Array
  • String
  • Set
  • Map
  • arguments
  • NodeList
  • 自定义对象(需实现 Symbol.iterator

5. SetMap 的迭代器

(1) Set 迭代

js 复制代码
let mySet = new Set(["apple", "banana", "cherry"]);
let setIter = mySet[Symbol.iterator]();

console.log(setIter.next()); // { value: 'apple', done: false }
console.log(setIter.next()); // { value: 'banana', done: false }
console.log(setIter.next()); // { value: 'cherry', done: false }
console.log(setIter.next()); // { value: undefined, done: true }

📌 Set 按插入顺序存储,迭代返回唯一值。


(2) Map 迭代

js 复制代码
let myMap = new Map([
  ["name", "Alice"],
  ["age", 25]
]);

for (let [key, value] of myMap) {
  console.log(key, value);
}
// name Alice
// age 25

📌 Map 迭代时返回 [key, value] 数组。


6. 迭代器 vs 生成器

特性 迭代器 (Iterator) 生成器 (Generator)
创建方式 手动实现 next() function* 生成
使用 Symbol.iterator 需要手动实现 生成器自动实现
可暂停执行 ❌ 否 ✅ 是(可 yield

示例:生成器

js 复制代码
function* generatorFunction() {
  yield "A";
  yield "B";
  yield "C";
}

let gen = generatorFunction();
console.log(gen.next()); // { value: 'A', done: false }
console.log(gen.next()); // { value: 'B', done: false }
console.log(gen.next()); // { value: 'C', done: false }
console.log(gen.next()); // { value: undefined, done: true }

📌 生成器更简洁,支持 yield 暂停执行


7. Iterator 使用场景

7.1 解构赋值

javascript 复制代码
// 对数组和 Set 结构进行解构赋值时,会默认调用 Iterator 接口
let set = new Set().add('a').add('b').add('c');
let [x, y] = set; // x='a'; y='b'

7.2 扩展运算符

javascript 复制代码
// 扩展运算符(...)也会调用默认的 Iterator 接口
let str = 'hello';
[...str] // ['h', 'e', 'l', 'l', 'o']

let arr = ['b', 'c'];
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd']

7.3 yield*

javascript 复制代码
// yield* 后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口
let generator = function* () {
  yield 1;
  yield* [2, 3, 4];
  yield 5;
};

for (let v of generator()) {
  console.log(v);
}
// 1, 2, 3, 4, 5

8. 注意事项

8.1 对象的 for...of 循环

javascript 复制代码
// 对象默认不具备 Iterator 接口,不能直接使用 for...of
let obj = { a: 1, b: 2, c: 3 };
for (let value of obj) {
  console.log(value); // TypeError: obj is not iterable
}

// 正确的遍历对象方式
// 1. 使用 Object.keys()
for (let key of Object.keys(obj)) {
  console.log(key + ': ' + obj[key]);
}

// 2. 使用 Object.entries()
for (let [key, value] of Object.entries(obj)) {
  console.log(key + ': ' + value);
}

8.2 Iterator 接口与 Generator 函数

javascript 复制代码
// 使用 Generator 函数实现 Iterator 接口
let obj = {
  *[Symbol.iterator]() {
    yield 'hello';
    yield 'world';
  }
};

for (let x of obj) {
  console.log(x);
}
// hello
// world

9. 最佳实践

9.1 为类部署 Iterator 接口

javascript 复制代码
class Collection {
  constructor() {
    this.items = [];
  }

  add(item) {
    this.items.push(item);
  }

  *[Symbol.iterator]() {
    for (let item of this.items) {
      yield item;
    }
  }
}

let collection = new Collection();
collection.add('foo');
collection.add('bar');

for (let value of collection) {
  console.log(value);
}
// foo
// bar

9.2 异步迭代器

javascript 复制代码
// ES2018 引入了异步迭代器
const asyncIterable = {
  async *[Symbol.asyncIterator]() {
    yield 'hello';
    yield 'async';
    yield 'iteration';
  }
};

(async () => {
  for await (const x of asyncIterable) {
    console.log(x);
  }
})();
// hello
// async
// iteration

10. 适用场景

适用于

  1. 遍历数组、字符串、Set、Map
  2. 自定义可迭代对象
  3. 流式处理数据(类似分页加载)
  4. 避免一次性加载大数据(生成器)

11. 总结

  • Iterator 是 ES6 提供的一种接口,用于顺序访问集合。
  • Symbol.iterator 让对象变成可迭代,可用于 for...ofspread
  • SetMapArrayString 默认实现 Symbol.iterator,可直接迭代。
  • 生成器 (Generator) 自动创建迭代器,可暂停执行 (yield),更强大。
相关推荐
ywf121525 分钟前
前端的dist包放到后端springboot项目下一起打包
前端·spring boot·后端
恋猫de小郭32 分钟前
2026,Android Compose 终于支持 Hot Reload 了,但是收费
android·前端·flutter
hpoenixf6 小时前
2026 年前端面试问什么
前端·面试
还是大剑师兰特7 小时前
Vue3 中的 defineExpose 完全指南
前端·javascript·vue.js
泯泷7 小时前
阶段一:从 0 看懂 JSVMP 架构,先在脑子里搭出一台最小 JSVM
前端·javascript·架构
mengchanmian8 小时前
前端node常用配置
前端
华洛8 小时前
利好打工人,openclaw不是企业提效工具,而是个人助理
前端·javascript·产品经理
xkxnq8 小时前
第六阶段:Vue生态高级整合与优化(第93天)Element Plus进阶:自定义主题(变量覆盖)+ 全局配置与组件按需加载优化
前端·javascript·vue.js
A黄俊辉A9 小时前
vue css中 :global的使用
前端·javascript·vue.js
小码哥_常9 小时前
被EdgeToEdge适配折磨疯了,谁懂!
前端