ES6 (ECMAScript 2015) 引入了许多强大的新特性,其中 for...of
循环和迭代器协议是处理集合数据的重要工具。它们为 JavaScript 提供了一种统一的方式来遍历各种数据结构,从数组到自定义对象。
for...of 循环基础
for...of
是 ES6 新增的循环语法,用于遍历可迭代对象(iterable)的值:
javascript
const arr = ['a', 'b', 'c'];
for (const value of arr) {
console.log(value); // 依次输出 'a', 'b', 'c'
}
与传统的 for
循环和 for...in
循环相比,for...of
提供了更简洁的语法来直接访问集合中的值,而不需要处理索引或键。
可迭代对象与迭代器协议
可迭代对象
一个对象要成为可迭代对象,必须实现 @@iterator
方法(即 Symbol.iterator
属性),该方法返回一个迭代器对象。
JavaScript 中内置的可迭代对象包括:
- Array
- String
- Map
- Set
- TypedArray
- 函数的 arguments 对象
- DOM 的 NodeList 对象
迭代器协议
迭代器是一个对象,它必须实现 next()
方法,该方法返回一个包含两个属性的对象:
value
:当前迭代的值done
:布尔值,表示迭代是否完成
javascript
const arrayIterator = ['a', 'b', 'c'][Symbol.iterator]();
console.log(arrayIterator.next()); // { value: 'a', done: false }
console.log(arrayIterator.next()); // { value: 'b', done: false }
console.log(arrayIterator.next()); // { value: 'c', done: false }
console.log(arrayIterator.next()); // { value: undefined, done: true }
自定义可迭代对象
我们可以通过实现 Symbol.iterator
方法来创建自定义的可迭代对象:
javascript
const myIterable = {
data: [1, 2, 3],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.data.length) {
return { value: this.data[index++], done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (const value of myIterable) {
console.log(value); // 1, 2, 3
}
for...of 的优势
- 简洁性:比传统的
for
循环更简洁 - 通用性:可以用于任何实现了迭代器协议的对象
- 避免错误:不需要手动管理索引或键
- 性能优化:某些情况下比
forEach
更高效
与其他循环的比较
for...in
:遍历对象的可枚举属性(包括原型链上的),不适合数组遍历forEach
:数组方法,不能用于其他可迭代对象,且不能使用break
或continue
for...of
:专门为可迭代对象设计,支持break
和continue
实际应用场景
-
遍历数组:
javascriptconst numbers = [1, 2, 3]; for (const num of numbers) { console.log(num); }
-
遍历字符串:
javascriptconst str = 'hello'; for (const char of str) { console.log(char); }
-
遍历 Map:
javascriptconst map = new Map([['a', 1], ['b', 2]]); for (const [key, value] of map) { console.log(key, value); }
-
与解构赋值结合:
javascriptconst users = [{name: 'Alice'}, {name: 'Bob'}]; for (const {name} of users) { console.log(name); }
注意事项
for...of
不能直接用于普通对象(除非实现了迭代器协议)- 某些旧环境可能需要 polyfill 来支持
for...of
- 在迭代过程中修改可迭代对象可能导致意外行为
总结
ES6 的 for...of
循环和迭代器协议为 JavaScript 提供了一种强大而统一的集合遍历机制。通过理解这些概念,开发者可以编写更简洁、更通用的代码来处理各种数据结构。无论是内置集合类型还是自定义对象,只要实现了迭代器协议,都可以使用 for...of
进行遍历,这使得代码更加一致和可维护。