pol*_*.ph 14 javascript clone generator ecmascript-6
我正在尝试List使用生成器在ES6中创建一个monad.为了使它工作,我需要创建一个已经消耗了几个状态的迭代器的副本.如何在ES6中克隆迭代器?
function* test() {
yield 1;
yield 2;
yield 3;
}
var x = test();
console.log(x.next().value); // 1
var y = clone(x);
console.log(x.next().value); // 2
console.log(y.next().value); // 2 (sic)
Run Code Online (Sandbox Code Playgroud)
我试着clone和cloneDeep从lodash,但他们是没有用的.以这种方式返回的迭代器是本机函数并在内部保持其状态,因此似乎没有办法用自己的JS代码来完成它.
迭代器[...]在内部保持状态,所以似乎没有办法
是的,这是有充分理由的.你不能克隆状态,否则你可能会篡改发电机太多.
然而,有可能通过记忆其序列并在以后再次产生它来创建第二个迭代器,该迭代器与第一个迭代器一起运行.但是,应该只有一个迭代器真正驱动生成器 - 否则,哪些克隆将被允许发送next()参数?
小智 5
你无法克隆生成器——它只是一个没有状态的函数。可以具有状态并因此可以克隆的是调用生成器函数所产生的迭代器。
这种方法会缓存中间结果,以便克隆的迭代器可以在必要时访问它们,直到它们“赶上”。它返回一个既是迭代器又是可迭代对象的对象,因此您可以调用next它或for...of覆盖它。任何迭代器都可以传入,因此理论上您可以通过传入 来克隆数组上的迭代器array.values()。无论哪个克隆next在迭代中的给定点首先调用,都会将参数传递给,如果有的话,反映在底层生成器中next的值中。yield
function clonableIterator(it) {
var vals = [];
return function make(n) {
return {
next(arg) {
const len = vals.length;
if (n >= len) vals[len] = it.next(arg);
return vals[n++];
},
clone() { return make(n); },
throw(e) { if (it.throw) it.throw(e); },
return(v) { if (it.return) it.return(v); },
[Symbol.iterator]() { return this; }
};
}(0);
}
function *gen() {
yield 1;
yield 2;
yield 3;
}
var it = clonableIterator(gen());
console.log(it.next());
var clone = it.clone();
console.log(clone.next());
console.log(it.next());Run Code Online (Sandbox Code Playgroud)
显然,这种方法存在一个问题,即它保留了迭代器的整个历史记录。一种优化是保留WeakMap所有克隆的迭代器以及它们的进度,然后清理历史记录以消除所有克隆已经消耗的所有过去的值。
| 归档时间: |
|
| 查看次数: |
1748 次 |
| 最近记录: |