我想知道是否有一种简单的方法可以将方法附加到实现“可迭代协议”的所有对象。我唯一能想到的就是为可迭代对象编写一个包装器,然后在那里定义方法。 (下面的片段用于演示目的。) 我当前的解决方案感觉相当笨拙。有没有更好的方法向我缺少的可迭代对象添加方法?
class Iterable {
static *forEach(iterable, fn) {
for (const value of iterable) {
fn(value);
yield value;
}
}
static *map(iterable, fn) {
for (const value of iterable) {
yield fn(value);
}
}
static *filter(iterable, fn) {
for (const value of iterable) {
if (fn(value)) yield value;
}
}
static *take(iterable, amount) {
const iterator = iterable[Symbol.iterator]();
for (;amount > 0; --amount) {
const {done, value} = iterator.next();
if (done) break;
yield value;
}
}
// ... additional iterable methods ...
constructor(iterable) {
this.iterable = iterable;
}
[Symbol.iterator]() {
return this.iterable[Symbol.iterator]();
}
toArray() {
return Array.from(this);
}
forEach(fn) {
return new this.constructor(Iterable.forEach(this, fn));
}
map(fn) {
return new this.constructor(Iterable.map(this, fn));
}
filter(fn) {
return new this.constructor(Iterable.filter(this, fn));
}
take(amount) {
return new this.constructor(Iterable.take(this, amount));
}
// ... additional iterable methods ...
}
const result = new Iterable([0,1,2,3,4,5,6,7,8,9])
.forEach(nr => console.log("initial:", nr))
.filter(nr => nr % 2)
.forEach(nr => console.log("filtered:", nr))
.map(nr => nr * 100)
.forEach(nr => console.log("mapped:", nr))
.take(2)
.forEach(nr => console.log("taken:", nr));
console.log("The iterable hasn't started iterating yet.");
console.log("result:", result.toArray()); // <- toArray will start the iteration proccess
但是,ECMAScript 2025 引入了
Iterator.prototype
,所有 core-JS 迭代器都继承自它。因此,如果您要为可迭代对象获取这样的实例,那么这就为某些迭代器辅助方法打开了大门。如果您确实愿意,您可以
将自己的添加到
Iterator.prototype
。
如果您从数组开始,那么您可以使用其
Iterator
方法获取这样的 .values()
实例,然后您可以链接
.map
、
.filter
...,它们现在是 JavaScript 原生的:
const arr = [1,2,3,4,5,6,7,8,9];
const it = arr.values().map(x => x ** 2).filter(x => x > 10);
console.log(it.next().value);
Iterator.from(iterable)
const arr = [1,2,3,4,5,6,7,8,9];
const it = Iterator.from(arr).map(x => x ** 2).filter(x => x > 10);
console.log(it.next().value);