JavaScript 迭代器是什么,以及在哪里可以使用它们?
JavaScript 迭代器是在 ES6 中引入的,它们用于循环遍历一系列的值,通常是某种集合。根据定义,迭代器必须实现一个 next()
函数,该函数返回一个形如 { value, done }
的对象,其中 value
是迭代序列中的下一个值,done
是一个布尔值,用于确定序列是否已经被消耗完。
一个在实际项目中有实际用途的非常简单的迭代器可以如下所示:
class LinkedList {
constructor(data) {
this.data = data;
}
firstItem() {
return this.data.find(i => i.head);
}
findById(id) {
return this.data.find(i => i.id === id);
}
[Symbol.iterator]() {
let item = { next: this.firstItem().id };
return {
next: () => {
item = this.findById(item.next);
if (item) {
return { value: item.value, done: false };
}
return { value: undefined, done: true };
},
};
}
}
const myList = new LinkedList([
{ id: 'a10', value: 'First', next: 'a13', head: true },
{ id: 'a11', value: 'Last', next: null, head: false },
{ id: 'a12', value: 'Third', next: 'a11', head: false },
{ id: 'a13', value: 'Second', next: 'a12', head: false },
]);
for (let item of myList) {
console.log(item); // 'First', 'Second', 'Third', 'Last'
}
在上面的示例中,我们实现了一个 LinkedList
数据结构,它在内部使用一个 data
数组。其中的每个项都有一个 value
和一些特定于实现的属性,用于确定它在序列中的位置。从该类构造的对象默认情况下不可迭代。为了定义一个迭代器,我们使用 Symbol.iterator
并设置它,使得返回的序列基于类的内部实现按顺序排列,而返回的项仅返回它们的 value
。
相关的是,迭代器只是函数,意味着它们可以像其他函数一样被调用(例如将迭代委托给现有的迭代器),同时不受Symbol.iterator
名称的限制。这使我们能够为同一个对象定义多个迭代器。下面是一个示例,展示了这些概念的运用:
class SpecialList {
constructor(data) {
this.data = data;
}
[Symbol.iterator]() {
return this.data[Symbol.iterator]();
}
values() {
return this.data
.filter(i => i.complete)
.map(i => i.value)
[Symbol.iterator]();
}
}
const myList = new SpecialList([
{ complete: true, value: 'Lorem ipsum' },
{ complete: true, value: 'dolor sit amet' },
{ complete: false },
{ complete: true, value: 'adipiscing elit' },
]);
for (let item of myList) {
console.log(item); // 与上面传递给SpecialList构造函数的确切数据相同
}
for (let item of myList.values()) {
console.log(item); // 'Lorem ipsum', 'dolor sit amet', 'adipiscing elit'
}
在这个示例中,我们使用data
对象的原生数组迭代器使我们的SpecialList
可迭代,返回data
数组的确切值。同时,我们还定义了一个values
方法,它本身就是一个迭代器,使用Array.prototype.filter()
和Array.prototype.map()
在data
数组上进行操作。最后,我们返回结果的Symbol.iterator
,只允许在序列中迭代非空对象,并且只返回每个对象的value
。