How do I reuse a generator in ES6 javascript in for loops?

时间:2017-11-11 13:35:00

标签: javascript ecmascript-6 iterator generator

I'm trying to write a function that can take either a list or a generator as input. For example, this function:

function x(l) {
    for (let i of l) {
        console.log(i);
    }
    for (let i of l) {
        console.log(i);
    }
}

If I run it like this:

x([1,2,3])

It will display:

1
2
3
1
2
3

Now I want to use a generator as input:

function *y() {
    yield 5
    yield 6
    yield 7
}

These don't work:

x(y())
x(y)

The output is:

5
6
7
undefined

What do I need to do so that I can make it work?

In terms of Java, the function y above is a Generator and y() is an Iterator. [1,2,3] is a list and in Java, lists are generators. But the javascript for loop expects an iterator, which means that it can't be restarted. This seems like a flaw in javascript that the for loop works on iterators and not generators.

1 个答案:

答案 0 :(得分:2)

生成器cannot be used multiple times。如果要迭代两次,则需要通过调用生成器函数两次来创建两个生成器。

当函数期望迭代(在for … of循环中使用)时,您可以执行的操作是从生成器函数动态创建一个:

x({[Symbol.iterator]: y})

如果你想编写你的函数x以便它可以使用迭代器或生成器函数,你可以使用像

这样的东西
getIterator(val) {
    if (typeof val == "function") // see also  https://stackoverflow.com/q/16754956/1048572
        return val();
    if (typeof val[Symbol.iterator] == "function")
        return val[Symbol.iterator]();
    throw new TypeError("not iterable!")
}
function x(l) {
    for (let i of getIterator(l)) {
        console.log(i);
    }
    for (let i of getIterator(l)) { // call getIterator again
        console.log(i);
    }
}
x(y);