javascript SyntaxError:意外标识符(ES6 中的生成器)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20834113/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 19:24:56  来源:igfitidea点击:

SyntaxError: Unexpected Identifier (Generators in ES6)

javascriptnode.jsgeneratoryieldecmascript-harmony

提问by Alix Axel

I came up with this simple experiment after reading the documentation on generators from MDN:

在阅读了MDN 中关于生成器文档后,我想出了这个简单的实验:

var nodes = {
    type: 'root',
    value: [
        { type: 'char', value: 'a' },
        { type: 'char', value: 'b' },
        { type: 'char', value: 'c' },
    ],
};

function* recursiveGenerator(node) {
    if (node.type === 'root') {
        node.value.forEach(function (subnode) {
            for (var suffix of recursiveGenerator(subnode)) {
                yield suffix;
            }
        });
    }

    else {
        yield node.value;
    }
}

for (generated of recursiveGenerator(nodes)) {
    console.log(generated);
}

Running it on node.js v0.11.9 with the --harmonyflag set produces the following error:

--harmony设置了标志的node.js v0.11.9 上运行它会产生以下错误:

alix@900X4C:~$ node --version
v0.11.9
alix@900X4C:~$ node --harmony test.js 

/home/alix/test.js:14
                yield suffix;
                      ^^^^^^
SyntaxError: Unexpected identifier

I also tried using for ... in ...and the letkeyword instead of var, but without any success.

我也尝试使用for ... in ...andlet关键字代替var,但没有成功。

I don't understand what yield*does exactly, but if I use it within the forloop I get instead:

我不明白究竟yield*是什么,但如果我在for循环中使用它,我会得到:

alix@900X4C:~$ node --harmony test.js 

/home/alix/test.js:14
                yield* suffix;
                ^
ReferenceError: yield is not defined

If I replace the yield in the for with console.log()it outputs a, band c. What am I doing wrong?

如果我将 for 中的 yield 替换为console.log()它的输出a,bc. 我究竟做错了什么?



Edit

编辑

Here's a minimalistic generator, showing that node.js knows what to do with generators:

这是一个简约的生成器,表明 node.js 知道如何处理生成器:

function* alpha() {
    yield 'a';
    yield 'b';
    yield 'c';
}

for (var suffix of alpha()) {
    console.log(suffix);
}

Output:

输出:

alix@900X4C:~$ node --harmony y.js 
a
b
c


Solution (thanks @Andrew)

解决方案(感谢@Andrew)

function* recursiveGenerator(node) {
    if (node.type === 'root') {
        for (var i = 0; i < node.value.length; ++i) {
            var subnode = node.value[i];

            for (var suffix of recursiveGenerator(subnode)) {
                yield suffix;
            }
        }
    }

    else {
        yield node.value;
    }
}

for (generated of recursiveGenerator(nodes)) {
    console.log(generated);
}

回答by vkurchatkin

Summarizing the comments: you can't use yieldinside a regularfunction, so you can't use yieldwith forEach. Here an example of "generatorized" foreach:

总结评论:您不能yield常规函数中使用,因此不能使用yieldwith forEach。这是“生成”foreach 的示例:

function * foreach (arr, fn) {
  var i

  for (i = 0; i < arr.length; i++) {
    yield * fn(arr[i])
  }
}

function * gen (number) {
  yield number + 1
  yield number + 2
  yield number + 3
}

function * other () {
  yield * foreach([1, 2, 3], gen)
}

for (var i of other()) {
    console.log(i)
}

UPDATEAlso the original problem can be solved quite elegantly using such a helper:

更新也可以使用这样的助手非常优雅地解决原始问题:

var nodes = {
  type: 'root',
  value: [
    { type: 'char', value: 'a' },
    { type: 'char', value: 'b' },
    { type: 'root', value: [
        { type: 'char', value: 'c' },
        { type: 'char', value: 'd' },
        { type: 'char', value: 'e' },
      ] 
    },
  ],
}

function * foreach (arr, fn) {
  var i

  for (i = 0; i < arr.length; i++) {
    yield * fn(arr[i])
  }
}

function * value (val) {
  yield val
}

function * recursiveGenerator(node) {
  yield * node.type === 'root' ?  foreach(node.value, recursiveGenerator) : value(node.value)
}

for (var generated of recursiveGenerator(nodes)) {
  console.log(generated);
}

So the generator itself becomes a one-liner!

所以发电机本身就变成了单线!

回答by nico

You've found your solution, but just for the record here is another example a little different that print the types of all nodes in the tree (I added some deepness and vars)

您已经找到了您的解决方案,但只是为了记录,这里是另一个稍微不同的示例,它打印树中所有节点的类型(我添加了一些深度和变量)

var nodes = {
    type: 'root',
    value: [
        { type: 'char', value: 'a' },
        { type: 'char', value: 'b' },
        { type: 'char', value: [{type: 'int', value: 'c'}] },
    ],
};

var flattenTree = function* (root) {
    yield root.type;
    var subvalues = root.value;
    for(var i in subvalues) {
        var gen = flattenTree(subvalues[i]);
        val = gen.next();
        while(!val.done) {
            if(val.value != undefined)
                yield val.value;
            val = gen.next();
        }
    }
}

var printTree = function() {
    console.log("begin tree");
    var generator = flattenTree(nodes);
    var next = generator.next();
    while(!next.done) {
        console.log(next);
        next = generator.next();
    }
    console.log("finish tree");
}

printTree();

Outputs:

输出:

~/workspace/tmp$ ../node/node --harmony test-gen.js 
begin tree
{ value: 'root', done: false }
{ value: 'char', done: false }
{ value: 'char', done: false }
{ value: 'char', done: false }
{ value: 'int', done: false }
finish tree