【问题标题】:In ES6, what happens to the arguments in the first call to an iterator's `next` method?在 ES6 中,第一次调用迭代器的 `next` 方法的参数会发生什么?
【发布时间】:2014-02-11 19:40:09
【问题描述】:

如果你有类似的生成器,

function* f () {
  // Before stuff.
  let a = yield 1;
  let b = yield 2;
  return [a,b];
}

然后,运行

var g = f();
// this question is over this value.
g.next(123); // returns: { value: 1, done: false }
g.next(456); // returns: { value: 2, done: false }
g.next(); // returns: { value: [ 456, undefined ], done: true }

第一次调用.next()a 设置为123,第二次调用将b 设置为456,但是在最后一次调用.next() 时返回,

{ value: [ 456, undefined ], done: true }

第一次调用g.next 时的参数会丢失吗?他们会发生什么?使用上面的例子,如何设置a

【问题讨论】:

标签: javascript generator v8 ecmascript-harmony


【解决方案1】:

试试:

var g = f();
// this question is over this value.
g.next(); // returns: { value: 1, done: false }
g.next(123); // returns: { value: 2, done: false }
g.next(456); // returns: { value: [123, 456], done: true }

【讨论】:

  • 所以第一个 .next() 的参数丢失了?这令人困惑......为什么不简单地在调用var g = f() 时运行第一个 .next() 为什么不作为 IteratorConstructor 的一部分调用一次呢?你什么时候会创建一个迭代器而不调用 .next() 来获得第一个收益?
  • 看起来第一个“next”启动了生成器,之后应该使用“send”来传递值,但是“next(foo)”是发送值的快捷方式in. 您可能不想立即开始执行生成器代码 - 第一个 .next() 为您提供了控制权。
  • 这很可能是真的,但是立即执行生成器代码,而只获得一个迭代器有什么好处呢?有没有方便的用例?而且,通常我可以在.next() 调用之前向生成器发送.send() 的东西吗?
  • 您可能不想立即开始执行代码(启动生成器类似于调用函数) - 这样,选择取决于您,而不是被规范强加。跨度>
  • @LJHarb 但是你不能做一些事情(使用原生生成器)来禁止在某处滥用生成器(比如在第一个 next 被错误值调用时抛出或记录),这可能会导致错误或性能问题在代码中
【解决方案2】:

传递给第一个 'next()' 调用的值将被忽略。看看这个ES6 TDD Coding Kata的最后一个测试(第34行)

对于那些对如何设置 ab 感到困惑的人,最好查看 Iterators & Generators 的“高级生成器”部分

【讨论】:

    【解决方案3】:

    来自 MDN Iterators and generators

    传递给 next() 的值将被视为暂停生成器的最后一个 yield 表达式的结果。

    答案:

    第一次调用 g.next 的参数会丢失吗?

    因为在第一次调用时没有last yield expression that paused the generator,所以这个值基本上被忽略了。你可以在ECMAScript 2015 Language Specification阅读更多内容。

    他们怎么了?

    在后续调用next() 时,传递的值将用作the return value of the last yield expression that paused the generator

    使用上面的例子,我该如何设置?

    您可以使用LJHarb suggested

    "use strict";
    
    let f = function*() {
    	let a = yield 1;
    	let b = yield 2;
    	return [a, b];
    };
    
    let g = f();
    
    document.querySelector("#log_1").innerHTML = JSON.stringify(g.next());
    document.querySelector("#log_2").innerHTML = JSON.stringify(g.next(123));
    document.querySelector("#log_3").innerHTML = JSON.stringify(g.next(456));
    <div id="log_1"></div>
    <div id="log_2"></div>
    <div id="log_3"></div>

    【讨论】:

      猜你喜欢
      • 2014-01-25
      • 2017-02-05
      • 2014-06-30
      • 2018-11-25
      • 1970-01-01
      • 1970-01-01
      • 2018-01-14
      • 1970-01-01
      • 2013-04-21
      相关资源
      最近更新 更多