JavaScript中的Symbol.iterator与可迭代协议
字数 776 2025-11-23 19:55:43
JavaScript中的Symbol.iterator与可迭代协议
描述
Symbol.iterator是JavaScript中的一个内置Symbol值,它定义了对象的默认迭代器。当一个对象实现了Symbol.iterator方法时,它就成为可迭代对象(iterable),可以使用for...of循环、扩展运算符等进行遍历。理解可迭代协议是掌握JavaScript迭代机制的关键。
详细讲解
1. 可迭代协议的基本概念
- 可迭代协议要求对象必须实现
@@iterator方法(即[Symbol.iterator]) - 该方法必须返回一个迭代器对象(iterator)
- 迭代器对象必须包含
next()方法,每次调用返回{value: any, done: boolean}格式的结果
// 基本结构示例
const iterable = {
[Symbol.iterator]() {
let step = 0;
return {
next() {
step++;
if (step <= 3) {
return { value: step, done: false };
}
return { value: undefined, done: true };
}
};
}
};
2. 内置可迭代对象分析
JavaScript中许多内置对象都是可迭代的:
// 数组
const arr = [1, 2, 3];
console.log(arr[Symbol.iterator]); // function values() { [native code] }
// 字符串
const str = "hello";
console.log(str[Symbol.iterator]); // function [Symbol.iterator]() { [native code] }
// Map和Set
const map = new Map();
console.log(map[Symbol.iterator]); // function entries() { [native code] }
3. 自定义可迭代对象实现
让我们创建一个范围迭代器:
class Range {
constructor(start, end, step = 1) {
this.start = start;
this.end = end;
this.step = step;
}
[Symbol.iterator]() {
let current = this.start;
const end = this.end;
const step = this.step;
return {
next() {
if ((step > 0 && current <= end) || (step < 0 && current >= end)) {
const value = current;
current += step;
return { value, done: false };
}
return { value: undefined, done: true };
}
};
}
}
// 使用示例
const range = new Range(1, 5);
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
4. 迭代器的返回值方法
迭代器还可以实现return()方法,用于在迭代提前结束时执行清理操作:
const cleanUpIterator = {
[Symbol.iterator]() {
return {
next() {
return { value: 'data', done: false };
},
return() {
console.log('执行清理操作');
return { done: true };
}
};
}
};
const iterator = cleanUpIterator[Symbol.iterator]();
console.log(iterator.next()); // {value: 'data', done: false}
iterator.return(); // 执行清理操作
5. 可迭代对象的实际应用场景
场景1:实现可迭代的链表
class ListNode {
constructor(value, next = null) {
this.value = value;
this.next = next;
}
}
class LinkedList {
constructor() {
this.head = null;
}
add(value) {
this.head = new ListNode(value, this.head);
}
[Symbol.iterator]() {
let current = this.head;
return {
next() {
if (current) {
const value = current.value;
current = current.next;
return { value, done: false };
}
return { done: true };
}
};
}
}
const list = new LinkedList();
list.add(3);
list.add(2);
list.add(1);
for (const item of list) {
console.log(item); // 1, 2, 3
}
场景2:无限序列生成器
function* fibonacci() {
let [prev, curr] = [0, 1];
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
const fib = fibonacci();
const sequence = {
[Symbol.iterator]: () => fib
};
let count = 0;
for (const num of sequence) {
if (count++ >= 10) break;
console.log(num); // 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
}
6. 可迭代协议与迭代器协议的区别
- 可迭代协议:对象必须实现
[Symbol.iterator]方法 - 迭代器协议:对象必须实现
next()方法 - 关系:可迭代对象的
[Symbol.iterator]()返回一个迭代器
7. 实际应用技巧
技巧1:检测对象是否可迭代
function isIterable(obj) {
return obj != null && typeof obj[Symbol.iterator] === 'function';
}
console.log(isIterable([1, 2, 3])); // true
console.log(isIterable({})); // false
技巧2:将类数组对象转换为可迭代对象
const arrayLike = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
// 添加迭代器使其可迭代
arrayLike[Symbol.iterator] = function() {
let index = 0;
return {
next: () => {
if (index < this.length) {
return { value: this[index++], done: false };
}
return { done: true };
}
};
};
// 现在可以使用for...of遍历
for (const item of arrayLike) {
console.log(item); // a, b, c
}
总结
Symbol.iterator和可迭代协议是JavaScript迭代机制的核心。通过实现[Symbol.iterator]方法,我们可以让自定义对象支持现代迭代语法,创建更加灵活和强大的数据结构和算法实现。