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

时间:2017-02-17 23:32:03

标签: javascript ecmascript-6 generator

function* foo() {
  yield 123
};

// - - -

function* foo() {
  return yield 123
};

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

  • 有明显不同吗?
  • return应该在发电机中使用吗?

2 个答案:

答案 0 :(得分:22)

首先,我首先要说发电机是一个有点复杂的话题,所以在这里给出一个完整的概述是不可能的。有关更多信息,我强烈推荐Kyle Simpson的You Don't Know JS系列。第5册(Async& Performance)对发电机的来龙去脉进行了很好的讨论。

在你给出的具体例子上!

首先,您在示例中编写的代码将显示无差异,但仅在正确运行时才显示。这是一个例子:

.next()

正如您所看到的,我并没有像正常功能一样调用生成器。生成器本身返回生成器对象(迭代器的一种形式)。我们将迭代器存储在变量中,并使用yield函数将迭代器推进到下一步(returnyield关键字)。

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} 关键字允许我们将值传递给生成器,这就是您的示例将以不同方式运行的位置。这是什么样子:

foo()

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

希望这有帮助!

答案 1 :(得分:11)

差异是最后一次继续调用的结果值:

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}

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

然而,还有一些发生器,其结果值很重要,例如,当它们被用作描述异步进程的工具时(在async / await promise语法的polyfill中,或者还有更多像CSP这样的东西)。在可迭代时使用return时,您还会获得yield* ed值。

在任何情况下,return yield一起听起来都不是很有用。