简体   繁体   English

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

[英]JS Generators: How is `return yield` different from `yield`?

function* foo() {
  yield 123
};

// - - -

function* foo() {
  return yield 123
};

I can't seem to demonstrate the difference between the two. 我似乎无法证明两者之间的区别。

  • Is there a demonstrable difference? 有明显的区别吗?
  • Should return be used in a generator? 应该return用于发电机吗?

First, I'll start by saying that Generators are a somewhat complicated topic, so giving a complete overview here won't be possible. 首先,我首先要说发电机是一个有点复杂的主题,所以在这里给出一个完整的概述是不可能的。 For more information I'd highly recommend Kyle Simpson's You Don't Know JS series. 有关更多信息,我强烈推荐Kyle Simpson的“ 你不知道JS系列”。 Book 5 (Async & Performance) has an excellent discussion on the ins and outs of generators. 第5册(异步和性能)对发电机的来龙去脉进行了很好的讨论。

Onto the specific example you gave though! 根据您给出的具体示例!

First, the code that you wrote in the example will show no difference but only if it's run correctly. 首先,您在示例中编写的代码将显示没有区别,前提是它运行正确。 Here's an example: 这是一个例子:

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}

As you can see, I'm not calling the generator like a normal function. 正如你所看到的,我并不像正常函数那样调用生成器。 The generator itself returns a generator object (a form of iterator). 生成器本身返回一个生成器对象 (迭代器的一种形式)。 We store that iterator in a variable and use the .next() function to advance the iterator to the next step (a yield or return keyword). 我们将迭代器存储在一个变量中,并使用.next()函数将迭代器推进到下一步( yieldreturn关键字)。

The yield keyword allows us to pass a value into the generator, and this is where your examples will run differently. yield关键字允许我们将值传递给生成器,这是您的示例以不同方式运行的地方。 Here's what that would look like: 这是什么样子:

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}

Notice that foo() will return undefined as a value, whereas bar() returns the number 2. This is because the value we're passing into the .next() call is sent to the return keyword and set as the return value. 请注意, foo()将返回undefined作为值,而bar()返回数字2.这是因为我们传入.next()调用的值被发送到return关键字并设置为返回值。 foo() has no explicit return statement, so you get the default undefined behavior. foo()没有显式的return语句,因此您将获得默认的undefined行为。

Hope that this helps! 希望这有帮助!

The difference is the result value of the last continuation call: 区别在于最后一次继续调用的结果值:

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}

Most generators don't need a return value, their purpose is the generation of a value stream as a side effect when they are running. 大多数生成器不需要return值,它们的目的是在运行时生成值流作为副作用。 All iterators are of this kind, if they are ran by a for of loop the result just signifies the end, but the value is discarded. 所有迭代器都属于这种类型,如果它们由for of循环运行,结果只表示结束,但该值被丢弃。

However, there also are generators where a result value is important, eg when they are used as a tool to describe asynchronous processes (in a polyfill for async / await promise syntax, or also many more things like CSP). 然而,也有发电机,其中当它们被用作描述异步进程(在一个填充工具工具的结果值是非常重要的,比如async / await承诺的语法,或者也有更多的东西像CSP)。 You also get the return ed value when using yield* on an iterable. 在iterable上使用yield*时,您还可以获得return值。

In any case, return yield together doesn't sound very useful. 无论如何,一起return yield并不是很有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM