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

前端 未结 5 2095
别跟我提以往
别跟我提以往 2020-12-09 09:34

I am using node 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));
}

f         


        
相关标签:
5条回答
  • 2020-12-09 10:03

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

    i.e. one too many }

    0 讨论(0)
  • 2020-12-09 10:06
    [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]

    unpack into flat array

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

    (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

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

    0 讨论(0)
  • 2020-12-09 10:07

    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));
    }
    
    0 讨论(0)
  • 2020-12-09 10:13

    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. Inside our generator, we have a single yield call which will yield the result of the numbers.map call, which is a new Array. Because there is only a single yield, the only logged value is [2,3,4]

    2. yield*

    So yield obviously won't work in the case above. 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 yielded by the generator. Inside our generator, we yield the same result of the numbers.map call, but this time we use yield*, which yield by delegation.

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


    Watchful eyes

    So we iterate thru numbers once using Array.prototype.map but then we iterate thru the intermediate array using the for loop? 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. Array.prototype.map creates a new array, but your generator doesn't do anything with it. So really you're just using map to iterate thru the numbers, not because you actually care about the returned value of 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

    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.

    0 讨论(0)
  • 2020-12-09 10:14

    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. 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,

    ArrowFunction : ArrowParameters => ConciseBody

    • It is a Syntax Error if ArrowParameters Contains YieldExpression is true.

    • It is a Syntax Error if ConciseBody Contains YieldExpression is true.

    0 讨论(0)
提交回复
热议问题