ES6生成器 - 第一个next()没有yield表达式的示例

dma*_*man 3 javascript ecmascript-harmony ecmascript-6

对于ES6生成器,为什么这篇博文的作者说:

来自:http://davidwalsh.name/es6-generators

"第一个下一个(..)调用,我们不发送任何内容.为什么?因为没有收益表达式来接收我们传入的内容."

不是第一次it.next()打电话(yield (x + 1))

function *foo(x) {
    var y = 2 * (yield (x + 1));
    var z = yield (y / 3);
    return (x + y + z);
}

var it = foo( 5 );

// note: not sending anything into `next()` here
console.log( it.next() );       // { value:6, done:false }
console.log( it.next( 12 ) );   // { value:8, done:false }
console.log( it.next( 13 ) );   // { value:42, done:true }
Run Code Online (Sandbox Code Playgroud)

您可以看到我们仍然可以使用初始foo(5)iterator-instantiation调用传递参数(在我们的示例中为x),就像使用普通函数一样.

第一个下一个(..)电话,我们不发送任何东西.为什么?因为没有收益表达式来接收我们传递的内容.

小智 6

第一个it.next()对应于yield(x + 1),其结果为预期的6.下一次调用中的12 it.next(12)将第一个yield的值设置为12,因此y将其设置为两倍,或24并且迭代器得到的值为(y / 3)8.最后调用it.next(13)将第二个yield的值设置为13,设置为z,并接收其值return,即5 + 24 + 13.

当然,由于语法原因,它有点令人困惑

z = yield(y / 3)
Run Code Online (Sandbox Code Playgroud)

这在某种程度上看起来像一个被分配的东西做的价值y / 3z.事实并非如此.y / 3是作为迭代器的值而z被赋予的值,而被分配给由以下 it.next()调用传入的值,这是完全不同的东西!省略括号并将其写为可能略有帮助

var y = 2 * yield x + 1;
var z = yield y / 3;
Run Code Online (Sandbox Code Playgroud)

请记住,这yield是一个声明,而不是函数调用.

至于你提到的错误,例如在traceur中它是"发送给新生的发电机的价值".当你想到它时,它是有道理的.作为参数发送的值将it.next()成为生成器中最新产量的值.在第一次调用it.next(),也就是没有最近在发电机的产量,所以没有什么拿的价值传递,因此错误.

不要将传递参数混淆到生成器(x在您的情况下),它仅提供配置或初始化生成器的方法,并将参数传递给生成器,该参数it.next()用作yield生成器中最新的值.

考虑如何编写等效的手动轧制发电机可能会有所帮助(简化为仅返回下一个值而不是{value, done},当发电机缺气时抛出):

function foo(x) {
    var y, z, step = 0;
    return function next(val) {
        switch (step++) {
            case 0:               return x + 1;      break;
            case 1: y = 2 * val;  return y / 3;      break;
            case 2: z = val;      return x + y + z;  break;
            default: throw "generator finished";
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

然后:

iterator = foo(5);
iterator();             // 6
iterator(12);           // 8
iterator(13);           // 42
Run Code Online (Sandbox Code Playgroud)