JS生成器:`return yield`与`yield`有什么不同?

Kir*_*eck 17 javascript generator ecmascript-6

function* foo() {
  yield 123
};

// - - -

function* foo() {
  return yield 123
};
Run Code Online (Sandbox Code Playgroud)

我似乎无法证明两者之间的区别.

  • 有明显的区别吗?
  • 应该return用在发电机上吗?

Jos*_*ter 27

首先,我首先要说发电机是一个有点复杂的主题,所以在这里给出一个完整的概述是不可能的.有关更多信息,我强烈推荐Kyle Simpson的" 你不知道JS系列".第5册(异步和性能)对发电机的来龙去脉进行了很好的讨论.

根据您提供的具体示例!

首先,您在示例中编写的代码将显示没有区别,前提是它运行正确.这是一个例子:

function* foo() {
  yield 123;
}

function* bar() {
  return yield 123;
}

var f = foo();
var b = bar();

f.next(); // {value: 123, done: false}
f.next(); // {value: undefined, done: true}
b.next(); // {value: 123, done: false}
b.next(); // {value: undefined, done: true}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我并不像正常函数那样调用生成器.生成器本身返回一个生成器对象(迭代器的一种形式).我们将迭代器存储在变量中,并使用该.next()函数将迭代器推进到下一步(a yieldreturn关键字).

yield关键字允许我们传递一个值到发电机,而这正是你的例子将运行不同.这是什么样子:

function* foo() {
  yield 123;
}

function* bar() {
  return yield 123;
}

var f = foo();
var b = bar();

// Start the generator and advance to the first `yield`
f.next(); // {value: 123, done: false}
b.next(); // {value: 123, done: false}

/** Now that I'm at a `yield` statement I can pass a value into the `yield`
 * keyword. There aren't any more `yield` statements in either function,
 * so .next() will look for a return statement or return undefined if one
 * doesn't exist. Like so:
 */
f.next(2); // {value: undefined, done: true}
b.next(2); // {value: 2, done: true}
Run Code Online (Sandbox Code Playgroud)

请注意,foo()它将undefined作为值bar()返回,而返回数字2.这是因为我们传入.next()调用的值将被发送到return关键字并设置为返回值.foo()没有明确的return语句,因此您获得默认undefined行为.

希望这有帮助!


Ber*_*rgi 12

区别在于最后一次继续调用的结果值:

function* fooA() {
  yield 123
};
var a = fooA();
console.log(a.next(1)); // {done:false, value:123}
console.log(a.next(2)); // {done:true,  value:undefined}

function* fooB() {
  return 40 + (yield 123)
};
var b = fooB();
console.log(b.next(1)); // {done:false, value:123}
console.log(b.next(2)); // {done:true,  value:42}
Run Code Online (Sandbox Code Playgroud)

大多数生成器不需要return值,它们的目的是在运行时生成值流作为副作用.所有迭代器都属于这种类型,如果它们由for of循环运行,结果只表示结束,但该值将被丢弃.

但是,还有一些生成器,其中结果值很重要,例如,当它们被用作描述异步进程的工具时(在polyfill for async/ awaitpromise语法中,或者还有更多的东西,如CSP).在iterable上return使用时,您还可以获得ed值yield*.

无论如何,return yield一起听起来并不是很有用.

  • @a_a 第一个 `.next(1)` 调用的参数 [被丢弃](/sf/ask/1488985151/)。最终结果来自添加`40`和`2`。 (2认同)