如何使用作为生成器并能够链接它们的函数来扩展数组?
How to extend the array with functions that are generators and able to chain them?
如何使用 returns 生成器对象的函数扩展 Array 并能够链接它们?
我已经尝试扩展数组以查看是否可以链接生成器函数。第一个调用有效,但下一个链不会,因为它 returns 一个生成器对象,我不知道如何扩展它。
Array.prototype.select = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) yield fn(item);
}
Array.prototype.where = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) {
if (fn(item)) yield item;
}
}
我希望能够将这样的生成器链接到数组
let result = arr.select(v => v * 2)
.where(v => v % 3 === 0);
for (let item of result) console.log(item);
如果你不介意过度扩展,第一个迭代器returns只是一个对象。
您可以通过 console.log(typeof arr.select(v => v * 2));
.
进行检查
因此,您可以简单地定义:Object.prototype.where = function* (fn) {};
Array.prototype.select = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) {
yield fn(item);
}
};
Object.prototype.where = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) {
if (fn(item)) yield item;
}
};
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let result = arr.select(v => v * 2)
.where(v => v % 3 === 0);
for (let item of result) {
console.log(item);
}
如果您希望顺序无关紧要,您可以像这样扩展 Array 和 Object。
Array.prototype.select = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) {
yield fn(item);
}
};
Array.prototype.where = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) {
if (fn(item)) yield item;
}
};
Object.prototype.select = Array.prototype.select;
Object.prototype.where = Array.prototype.where;
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// Chain 1.
let result1 = arr.select(v => v * 2).where(v => v % 3 === 0);
console.log('Chain 1');
for (const item of result1) {
console.log(item);
}
// Chain 2.
let result2 = arr.where(v => v % 3 === 0).select(v => v * 2);
console.log('Chain 2')
for (const item of result2) {
console.log(item);
}
您可以将这两个方法存储为 Object
的原型函数并移交迭代器对象,因为这两个函数都采用生成器和 returns 可迭代对象。
Object.prototype.select = function* (fn) {
for (let v of this) yield fn(v);
}
Object.prototype.where = function* (fn) {
for (let v of this[Symbol.iterator]()) if (fn(v)) yield v;
}
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9],
result = array[Symbol.iterator]()
.select(v => v * 2)
.where(v => v % 3 === 0);
console.log(...result);
在不修改 Object
的情况下,您仍然可以使用我创造的技术 .
使这些方法可链接
你首先定义你的基础 class,Array
将扩展它,然后你修改 Array
的原型链来人为地扩展你的基础 class。
请注意 select()
和 where()
方法如何将您的原始生成器函数封装到 class 的 return 个新实例中,以便这些方法是可链接的。
class Enumerable {
constructor (getIterator) {
this[Symbol.iterator] = getIterator;
}
select (fn) {
return new Enumerable(function * () {
for (const value of this) {
yield fn(value);
}
}.bind(this));
}
where (fn) {
return new Enumerable(function * () {
for (const value of this) {
if (fn(value)) yield value;
}
}.bind(this));
}
}
Object.setPrototypeOf(Array, Enumerable);
Object.setPrototypeOf(Array.prototype, Enumerable.prototype);
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const result = array
.select(v => v * 2)
.where(v => v % 3 === 0);
for (const item of result) {
console.log(item);
}
如何使用 returns 生成器对象的函数扩展 Array 并能够链接它们?
我已经尝试扩展数组以查看是否可以链接生成器函数。第一个调用有效,但下一个链不会,因为它 returns 一个生成器对象,我不知道如何扩展它。
Array.prototype.select = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) yield fn(item);
}
Array.prototype.where = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) {
if (fn(item)) yield item;
}
}
我希望能够将这样的生成器链接到数组
let result = arr.select(v => v * 2)
.where(v => v % 3 === 0);
for (let item of result) console.log(item);
如果你不介意过度扩展,第一个迭代器returns只是一个对象。
您可以通过 console.log(typeof arr.select(v => v * 2));
.
因此,您可以简单地定义:Object.prototype.where = function* (fn) {};
Array.prototype.select = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) {
yield fn(item);
}
};
Object.prototype.where = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) {
if (fn(item)) yield item;
}
};
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let result = arr.select(v => v * 2)
.where(v => v % 3 === 0);
for (let item of result) {
console.log(item);
}
如果您希望顺序无关紧要,您可以像这样扩展 Array 和 Object。
Array.prototype.select = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) {
yield fn(item);
}
};
Array.prototype.where = function* (fn) {
let it = this[Symbol.iterator]();
for (let item of it) {
if (fn(item)) yield item;
}
};
Object.prototype.select = Array.prototype.select;
Object.prototype.where = Array.prototype.where;
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// Chain 1.
let result1 = arr.select(v => v * 2).where(v => v % 3 === 0);
console.log('Chain 1');
for (const item of result1) {
console.log(item);
}
// Chain 2.
let result2 = arr.where(v => v % 3 === 0).select(v => v * 2);
console.log('Chain 2')
for (const item of result2) {
console.log(item);
}
您可以将这两个方法存储为 Object
的原型函数并移交迭代器对象,因为这两个函数都采用生成器和 returns 可迭代对象。
Object.prototype.select = function* (fn) {
for (let v of this) yield fn(v);
}
Object.prototype.where = function* (fn) {
for (let v of this[Symbol.iterator]()) if (fn(v)) yield v;
}
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9],
result = array[Symbol.iterator]()
.select(v => v * 2)
.where(v => v % 3 === 0);
console.log(...result);
在不修改 Object
的情况下,您仍然可以使用我创造的技术
你首先定义你的基础 class,Array
将扩展它,然后你修改 Array
的原型链来人为地扩展你的基础 class。
请注意 select()
和 where()
方法如何将您的原始生成器函数封装到 class 的 return 个新实例中,以便这些方法是可链接的。
class Enumerable {
constructor (getIterator) {
this[Symbol.iterator] = getIterator;
}
select (fn) {
return new Enumerable(function * () {
for (const value of this) {
yield fn(value);
}
}.bind(this));
}
where (fn) {
return new Enumerable(function * () {
for (const value of this) {
if (fn(value)) yield value;
}
}.bind(this));
}
}
Object.setPrototypeOf(Array, Enumerable);
Object.setPrototypeOf(Array.prototype, Enumerable.prototype);
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const result = array
.select(v => v * 2)
.where(v => v % 3 === 0);
for (const item of result) {
console.log(item);
}