如何在JavaScript中克隆迭代器



在ES6中,是否有可能克隆迭代器状态?

var ma=[1,2,3,4];
var it=ma[Symbol.iterator]();
it.next();

如果我想在这里记住IT指出我应该在Javascritp中该怎么做?

其中有什么?因为

JSON.stringify(it) //it would just return {}

您不能克隆任意的迭代器,但是您可以通过保持某种状态来创建与一个迭代器的许多不同的迭代器:

function tee(iterable) {
    const source = iterable[Symbol.iterator]();
    const buffers = [[], []];  // substitute in queue type for efficiency
    const DONE = Object.create(null);
    const next = i => {
        if (buffers[i].length !== 0) {
            return buffers[i].shift();
        }
        const x = source.next();
        if (x.done) {
            return DONE;
        }
        buffers[1 - i].push(x.value);
        return x.value;
    };
    return buffers.map(function* (_, i) {
        for (;;) {
            const x = next(i);
            if (x === DONE) {
                break;
            }
            yield x;
        }
    });
}

用法:

const [a, b] = tee(iterator);
assert(a.next().value === b.next().value);

不可能克隆迭代器。迭代器状态基本上是完全任意的,任何给定的迭代器都可能需要或产生副作用(例如,从或写入网络流到网络流)是不可按需重复的。

这还不是官方的,但是我认为在第2阶段的建议中可能有一个解决方案。如果这些方法不影响原始迭代器,则执行诸如iter.take(Infinity)iter.drop(0)之类的操作与克隆具有相同的效果。

我构建了一个库,允许您在此处分配迭代器:https://github.com/tjenkinson/forkable-iterator

表示您可以做类似:

的事情
import { buildForkableIterator, fork } from 'forkable-iterator';
function* Source() {
  yield 1;
  yield 2;
  return 'return';
}
const forkableIterator = buildForkableIterator(Source());
console.log(forkableIterator.next()); // { value: 1, done: false }
const child1 = fork(forkableIterator);
// { value: 2, done: false }
console.log(child1.next());
// { value: 2, done: false }
console.log(forkableIterator.next());
// { value: 'return', done: true }
console.log(child1.next());
// { value: 'return', done: true }
console.log(forkableIterator.next());

如果您不再需要从叉子中消耗掉叉子,从而使您的引用松动,也不应该有记忆泄漏。

最新更新