TypeScript: Symbol.iterator属性
Symbol.iterator
是ES6引入的特殊内置Symbol,用于定义对象的默认迭代器行为。在TypeScript中,它使对象成为可迭代对象(Iterable),可与for...of
、展开运算符...
等语法配合使用。
一、核心概念解析
迭代协议:
可迭代协议:对象必须实现
[Symbol.iterator]
方法,返回一个迭代器对象。迭代器协议:迭代器对象必须包含
next()
方法,返回{ value: T, done: boolean }
。
Symbol.iterator
的作用:定义对象如何被迭代(如数组、Map、Set原生支持)
自定义对象可通过实现它获得迭代能力
TypeScript中通过
Iterable<T>
接口增强类型安全
二、实现原理与代码示例
1. 原生对象的迭代(以数组为例)
const arr: number[] = [10, 20, 30];
const iterator: IterableIterator<number> = arr[Symbol.iterator]();console.log(iterator.next()); // { value: 10, done: false }
console.log(iterator.next()); // { value: 20, done: false }
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
2. 自定义可迭代对象(实现链表)
class ListNode<T> {constructor(public value: T, public next?: ListNode<T>) {}
}class LinkedList<T> implements Iterable<T> {constructor(private head?: ListNode<T>) {}// 实现Symbol.iterator方法[Symbol.iterator](): Iterator<T> {let current = this.head;return {next: (): IteratorResult<T> => {if (current) {const value = current.value;current = current.next;return { value, done: false };}return { value: undefined, done: true };}};}
}// 使用示例
const list = new LinkedList<number>(new ListNode(1, new ListNode(2, new ListNode(3)))
);// for...of自动调用迭代器
for (const num of list) {console.log(num); // 输出: 1 → 2 → 3
}
3. 结合生成器函数简化实现
class Range implements Iterable<number> {constructor(private start: number,private end: number,private step: number = 1) {}*[Symbol.iterator](): IterableIterator<number> {for (let i = this.start; i <= this.end; i += this.step) {yield i; // 利用生成器自动管理迭代状态}}
}// 使用展开运算符
console.log([...new Range(5, 10)]); // [5, 6, 7, 8, 9, 10]
三、关键特性与工程实践
1.类型安全:
使用泛型约束迭代值类型(如
IterableIterator<string>
)实现
Iterable<T>
接口确保类型检查
function sum(iter: Iterable<number>): number {let total = 0;for (const num of iter) total += num;return total;
}
2.性能优化:
惰性求值:迭代器按需生成值,节省内存(对比一次性生成数组)
无限序列:可创建无限迭代器(如斐波那契数列)
3.前端应用场景:
自定义树结构遍历(DOM树、组件树)
分页数据流处理
异步迭代(配合
Symbol.asyncIterator
)
四、与相关概念的对比
特性 | Symbol.iterator | 数组forEach |
---|---|---|
执行机制 | 惰性迭代 | 立即执行 |
内存占用 | 低(按需生成) | 高(预生成所有元素) |
中断能力 | 支持break /return 中断 | 无法中断 |
适用对象 | 任何实现迭代协议的对象 | 仅数组 |
总结
作为前端工程师,掌握Symbol.iterator
的核心价值在于:
统一处理异构数据:使自定义数据结构(如链表、树)获得与原生数组相同的迭代能力
提升性能与内存效率:惰性迭代特别适合处理大型数据集或流式数据
增强代码抽象性:通过迭代协议解耦数据结构和遍历逻辑
类型安全强化:TypeScript的泛型和接口确保迭代过程类型正确
工程实践中,优先使用生成器函数(function*
)简化迭代器实现,并注意在异步场景使用Symbol.asyncIterator
扩展。