Can I pass a parameter to ES6 generator function

This great article about generator answered my question, input1 has been tossed away, there's no way to access it. It's weird but true


When you obtain the generator you don't have yields you can push value to (you are at the beginning of the generator function). You need to trigger the generator and reach the first yield by calling gen.next() without any arguments. At this point you have an yield at your disposal and you can push your value via gen.next('input1') effectively replacing the expression yield 'output1' with the value you passed to next - 'input1'. Then you need another yield or a return to provide your custom value to the consumer of the generator. Here is the code:

function *Gen() {
    var input1 = yield 'output1'
    return input1
}

var gen = Gen()

gen.next();
gen.next('input1').value // return 'input1'

First, let's simply this example:

function *createGenerator(input) {
    yield input
}

var generator = createGenerator('input')

console.log(
    generator
    .next()
    .value
)
// input

So you can pass a value into the generator on creation and pull it out, but if you've already created the generator, the only way to get a value in is by passing it through .next. But which .next?

function *createGenerator() {
    const input = yield
    yield input
}

var generator = createGenerator()

console.log(
    generator
    .next('input1')
    .value
)
// undefined

console.log(
    generator
    .next('input2')
    .value
)
// input2

As you can see in this example, the first input doesn't come through, but the second does. That's because your code executes in a generator up to the first yield and then stops. Because of that, the first value you pass in will be missing because there's no code to evaluate it.

Let's look at another example:

function *createGenerator() {
    const input1 = yield
    const input2 = yield input1
    yield input2
}

var generator = createGenerator()

console.log(
    generator
    .next('input0')
    .value
)
// undefined

console.log(
    generator
    .next('input1')
    .value
)
// input1

console.log(
    generator
    .next('input2')
    .value
)
// input2

console.log(
    generator
    .next('input3')
    .value
)
// undefined

When you call .next the second time, you evaluate the value passed in, and keep processing code until the next yield. In this case, you execute yield input, but nothing to the left of it because that's technically the "next line" of execution in JavaScript's AST.


If you want a parametrised generator function you can use a higher order function that returns generator:

function myGenerator(startFrom) {
    return (function *() {
        var i = startFrom;
        while (true) yield i++;
    })();
}

var gen = myGenerator(5);
console.log(gen.next().value) // 5
console.log(gen.next().value) // 6
console.log(gen.next().value) // 7

Higher order generators can be of use too:

function getGenerator(baseStartFrom, expStartFrom) {
    return (function *() {
        var a = baseStartFrom;
        while (true) {
          yield (function *() {
              var i = expStartFrom;
              while (true) yield Math.pow(a, i++);
          })();
          a++;
        }
    })();
}

var gen = getGenerator(2, 3);
var gen2 = gen.next().value; // generator yields powers of 2
  console.log(gen2.next().value); // 8
  console.log(gen2.next().value); // 16
  console.log(gen2.next().value); // 32
var gen3 = gen.next().value; // generator yields powers of 3
  console.log(gen3.next().value); // 27
  console.log(gen3.next().value); // 81
  console.log(gen3.next().value); // 243

The sample is most likely useless but the same approach can be used, for example, to generate random number generators.