Javascript 为什么在这种情况下调用 ES6 “yield” 是保留字?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33316765/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:57:03  来源:igfitidea点击:

Why is ES6 "yield" a reserved word when called in this context?

javascriptnode.jsecmascript-6

提问by Mike Hogan

I am using node 4.1.1. When I run this code

我正在使用节点 4.1.1。当我运行此代码时

"use strict";

function *generator() {
  let numbers = [1,2,3,4,5];
  numbers.map(n => yield (n + 1));
}

for (var n of generator()) {
  console.log(n);
}

I get this error

我收到这个错误

  numbers.map(n => yield (n + 1));
                   ^^^^^

SyntaxError: Unexpected strict mode reserved word

If I rearrange the code to be this

如果我将代码重新排列成这样

"use strict";

function *generator() {
  let numbers = [1,2,3,4,5];
  let higherNumbers = numbers.map(n => n + 1);
  for(let i=0;i<higherNumbers.length;i++) {
    yield higherNumbers[i];
  }
}

for (var n of generator()) {
  console.log(n);
}

I get the expected result.

我得到了预期的结果。

Why does the second one work, and the first fail? And surely if a keyword is reserved, it's reserved in all contexts, not just when it's used in a arrow function?

为什么第二个有效,而第一个失败?当然,如果一个关键字被保留,它在所有上下文中都会被保留,而不仅仅是在箭头函数中使用时?

采纳答案by thefourtheye

It is because arrow functions are not generator functions. For example,

这是因为箭头函数不是生成器函数。例如,

function temp() {
  yield 1;
}

Can we expect this to work? No. Because tempis not a generator function. The same is applicable to arrow functions as well.

我们可以期望这有效吗?temp不。因为不是生成器函数。这同样适用于箭头函数。



FWIW, the usage of yieldin an Arrow function is an early error as per the ECMAScript 2015 specification, as per this section,

FWIW,根据yieldECMAScript 2015 规范,在箭头函数中的使用是早期错误,根据本节

ArrowFunction : ArrowParameters => ConciseBody

  • It is a Syntax Error if ArrowParametersContains YieldExpressionis true.

  • It is a Syntax Error if ConciseBodyContains YieldExpressionis true.

ArrowFunction : ArrowParameters => ConciseBody

  • 如果ArrowParameters包含YieldExpressiontrue ,则这是一个语法错误。

  • 如果ConciseBodyContains YieldExpressiontrue,则为语法错误。

回答by Thank you

You can do anything but not everything – Learn to delegate

你可以做任何事,但不能做任何事——学会委派

Let's first look at two examples

我们先来看两个例子

1. yield

1.产量

function* generator(numbers) {
  yield numbers.map(x => x + 1);
}

for (let n of generator([1,2,3])) console.log(n);
// [ 2, 3, 4 ]

Our forloop logs each value yielded by the generator. Inside our generator, we have a single yieldcall which will yield the result of the numbers.mapcall, which is a new Array. Because there is only a single yield, the only logged value is [2,3,4]

我们的for循环记录了生成器产生的每个值。在我们的生成器中,我们有一个yield调用将产生调用的结果numbers.map,这是一个新的数组。因为只有一个产量,所以唯一记录的值是[2,3,4]

2. yield*

2. yield*

So yieldobviously won't work in the case above. We'll have to try something else.

所以yield显然在上面的情况下不起作用。我们将不得不尝试别的东西。

function* generator(numbers) {
  yield* numbers.map(x => x + 1);
}

for (let n of generator([1,2,3])) console.log(n);
// 2
// 3
// 4

Again, our forloop logs each value yielded by the generator. Inside our generator, we yield the same result of the numbers.mapcall, but this time we use yield*, which yield by delegation.

同样,我们的for循环记录yield了生成器 ed 的每个值。在我们的生成器中,我们产生与numbers.map调用相同的结果,但这次我们使用yield*,它由委托产生

What are we yielding then? Well, Array's have a built-in generator, Array.prototype[Symbol.iterator]. So at this point, the forloop is essentially directly stepping thru the generator provided by the Array. Since the array has 3 values, we see 3 logged values.

那我们要屈服什么?好吧,Array 有一个内置的生成器,Array.prototype[Symbol.iterator]. 所以在这一点上,for循环本质上是直接通过 Array 提供的生成器。由于数组有 3 个值,我们看到 3 个记录值。



Watchful eyes

警惕的眼神

So we iterate thru numbersonce using Array.prototype.mapbut then we iterate thru the intermediate array using the forloop? Seems like a waste doesn't it?

因此,我们使用循环遍历numbers一次Array.prototype.map,然后使用循环遍历中间数组for?好像很浪费是不是?

Let's look back at your original code though

让我们回顾一下你的原始代码

function *generator() {
  let numbers = [1,2,3,4,5];
  numbers.map(n => yield (n + 1));
}

for (var n of generator()) {
  console.log(n);
}

Notice that your numbers.mapcall is pretty meaningless. Array.prototype.mapcreates a new array, but your generator doesn't doanything with it. So reallyyou're just using mapto iterate thru the numbers, not because you actually care about the returned value of map

请注意,您的numbers.map通话毫无意义。Array.prototype.map创建一个新数组,但您的生成器不会对它任何事情。所以实际上你只是map用来遍历数字,而不是因为你实际上关心的返回值map



Say what you mean, mean what you say

说你的意思,说你的意思

OK, so now we know we only really care about iterating thru the numbers. So we'll use iterationthe way JavaScript knows best

好的,现在我们知道我们只关心遍历数字。所以我们将以JavaScript 最了解的方式使用迭代

function* generator(numbers) {
  for (let x of numbers)
    yield x + 1
}

for (let n of generator([1,2,3])) console.log(n);
// 2
// 3
// 4

Bingo. No tricky yield*. No double iteration. No nonsense.

答对了。不难yield*。没有双重迭代。没有废话。

回答by Joseph

That's because the arrow function is not a generator. If I expand your arrow function, it would look something like:

那是因为箭头函数不是生成器。如果我展开你的箭头函数,它看起来像:

function *generator() {      // <-- this is your generator function
  let numbers = [1,2,3,4,5];
  numbers.map(function(n){   // <-- this one isn't a generator
    yield (n + 1)            // <-- there's your yield
  }.bind(this));
}

回答by ErichBSchulz

Just discovered you can encounter this by accidentally closing your function too early.

刚刚发现您可能会因意外过早关闭函数而遇到此问题。

i.e. one too many }

即一个太多 }

回答by Eric

[1,2,3,4,5].map(function*(v){yield v+1;}).reduce((accumulator, currentValue) => accumulator = [...accumulator].concat([...currentValue]))

explanation...

解释...

[1,2,3,4,5].map(function*(v){yield v+1;})

pack all values into generator resulting

将所有值打包到生成器中

(5)?[Generator, Generator, Generator, Generator, Generator]

(5)?[发电机,发电机,发电机,发电机,发电机]

unpack into flat array

解压成平面阵列

.reduce((accumulator, currentValue) => accumulator = [...accumulator].concat([...currentValue]))

(5)?[2, 3, 4, 5, 6]

(5)?[2, 3, 4, 5, 6]

for normal use

正常使用

[1,2,3,4,5].map(function*(v){yield v+1;}).forEach(v => console.log([...v][0]))

2

3

4

5

6

2

3

4

5

6

[...v][0] is a bit ugly but it is works.

[...v][0] 有点难看,但它是有效的。