for..of和迭代器状态

geo*_*org 6 javascript iterator yield

考虑一下这个python代码

it = iter([1, 2, 3, 4, 5])

for x in it:
    print x
    if x == 3:
        break

print '---'

for x in it:
    print x
Run Code Online (Sandbox Code Playgroud)

它会打印1 2 3 --- 4 5,因为迭代器会it记住它在循环中的状态.当我在JS中看似相同的事情时,我得到的只是1 2 3 ---.

function* iter(a) {
    yield* a;
}

it = iter([1, 2, 3, 4, 5])

for (let x of it) {
    console.log(x)
    if (x === 3)
        break
}

console.log('---')

for (let x of it) {
    console.log(x)
}
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

And*_*rey 6

不幸的是,JS中的Generator对象不可重用.在MDN上明确说明

生成器不应该被重用,即使for ... of循环提前终止,例如通过break关键字.退出循环后,生成器关闭并尝试再次迭代它不会产生任何进一步的结果.


geo*_*org -1

正如其他答案中所指出的,for..of在任何情况下都会关闭迭代器,因此需要另一个包装器来保留状态,例如

function iter(a) {
    let gen = function* () {
        yield* a;
    }();

    return {
        next() {
            return gen.next()
        },
        [Symbol.iterator]() {
            return this
        }
    }
}


it = iter([1, 2, 3, 4, 5]);

for (let x of it) {
    console.log(x);
    if (x === 3)
        break;
}

console.log('---');

for (let x of it) {
    console.log(x);
}
Run Code Online (Sandbox Code Playgroud)