简体   繁体   English

为什么在这种情况下调用ES6会“产生”一个保留字?

[英]Why is ES6 “yield” a reserved word when called in this context?

I am using node 4.1.1. 我正在使用节点4.1.1。 When I run this code 当我运行此代码时

"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? 当然,如果保留一个关键字,它会在所有上下文中保留,而不仅仅是在箭头函数中使用它?

You can do anything but not everything – Learn to delegate 你可以做任何事情而不是一切 - 学会委派

Let's first look at two examples 我们先来看两个例子

1. yield 产量

 function* generator(numbers) { yield numbers.map(x => x + 1); } for (let n of generator([1,2,3])) console.log(n); // [ 2, 3, 4 ] 

Our for loop logs each value yielded by the generator. 我们的for循环记录了生成器产生的每个值。 Inside our generator, we have a single yield call which will yield the result of the numbers.map call, which is a new Array. 在我们的生成器中,我们有一个yield调用,它将产生numbers.map调用的结果,这是一个新的Array。 Because there is only a single yield, the only logged value is [2,3,4] 因为只有一个产量,所以唯一记录的值是[2,3,4]

2. yield* yield*

So yield obviously won't work in the case above. 因此,在上述情况下, yield显然不会起作用。 We'll have to try something else. 我们必须尝试别的东西。

 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 for loop logs each value yield ed by the generator. 同样,我们for循环日志的每个值yield由发电机编。 Inside our generator, we yield the same result of the numbers.map call, but this time we use yield* , which yield by delegation . 在我们的生成器中,我们产生了与numbers.map调用相同的结果,但这次我们使用yield* ,它通过委托产生

What are we yielding then? 那我们收获的是什么? Well, Array's have a built-in generator, Array.prototype[Symbol.iterator] . 好吧,Array有一个内置的生成器, Array.prototype[Symbol.iterator] So at this point, the for loop is essentially directly stepping thru the generator provided by the Array. 所以在这一点上, for循环基本上直接通过Array提供的生成器步进。 Since the array has 3 values, we see 3 logged values. 由于数组有3个值,我们看到3个记录值。


Watchful eyes 注视着眼睛

So we iterate thru numbers once using Array.prototype.map but then we iterate thru the intermediate array using the for loop? 所以我们使用Array.prototype.map迭代numbers一次但是然后我们使用for循环遍历中间数组? Seems like a waste doesn't it? 好像浪费不是吗?

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.map call is pretty meaningless. 请注意,您的numbers.map调用非常无意义。 Array.prototype.map creates a new array, but your generator doesn't do anything with it. Array.prototype.map创建一个新数组,但您的生成器不会对它执行任何操作。 So really you're just using map to iterate thru the numbers, not because you actually care about the returned value of 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 iteration the 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* . 没有棘手的yield* No double iteration. 没有双重迭代。 No nonsense. 没有废话。

It is because arrow functions are not generator functions. 这是因为箭头功能不是发电机功能。 For example, 例如,

function temp() {
  yield 1;
}

Can we expect this to work? 我们可以期待这个吗? No. Because temp is not a generator function. 不。因为temp不是发电机功能。 The same is applicable to arrow functions as well. 这同样适用于箭头功能。


FWIW, the usage of yield in an Arrow function is an early error as per the ECMAScript 2015 specification, as per this section , FWIW,根据ECMAScript 2015规范,箭头函数中yield的使用是一个早期错误,按照本节的规定

ArrowFunction : ArrowParameters => ConciseBody ArrowFunction:ArrowParameters => ConciseBody

  • It is a Syntax Error if ArrowParameters Contains YieldExpression is true . 如果ArrowParameters包含YieldExpressiontrue ,则为语法错误。

  • It is a Syntax Error if ConciseBody Contains YieldExpression is true . 如果ConciseBody包含YieldExpressiontrue ,则为语法错误。

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));
}
[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 2

3 3

4 4

5

6 6

[...v][0] is a bit ugly but it is works. [... v] [0]有点丑,但它确实有效。

Just discovered you can encounter this by accidentally closing your function too early. 刚刚发现你可能会因为过早地关闭你的功能而遇到这种情况。

ie one too many } 即太多了}

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

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