我可以为ES6生成器函数传递参数吗?

14

这是一个 ES6 生成器:

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

var gen = Gen()

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

第一次调用gen时,返回output1,但变量input1的值不等于传入的'input1',实际上input的值是'input2'。第二次调用时,调用了next('input2')

我的问题是如何访问第一次调用时的input1,类似于:

function *Gen() {
    var input 1 = param1
    var input2 = yield 'output1'
}

1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - user663031
5个回答

26
当你获得生成器时,你没有可以推送值的yield(你处于生成器函数的开头)。你需要触发生成器并通过调用gen.next()(不带任何参数)到达第一个yield。此时,你可以使用yield并通过gen.next('input1')将你的值传递给生成器,有效地替换表达式yield 'output1'中的值为你传递给next的值 - 'input1'。接着,你需要另一个yield或者一个return来向生成器的消费者提供你自定义的值。以下是代码:
function *Gen() {
    var input1 = yield 'output1'
    return input1
}

var gen = Gen()

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

2
当您获取生成器时,如果您没有可推送值的产出(即您位于生成器函数的开头),则可以+1。 - RIYAJ KHAN

7

这篇关于生成器的好文章回答了我的问题,输入1已经被抛弃,没有访问它的方法。虽然有些奇怪,但确实如此。


2
请在您的回答中包含文章的相关部分,否则如果链接失效,它将不再有任何价值。 - totymedli

3

首先,让我们简化这个例子:

function *createGenerator(input) {
    yield input
}

var generator = createGenerator('input')

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

因此,您可以在创建生成器时传递一个值并提取它,但是如果您已经创建了生成器,则唯一的方法是通过.next传递它。但是哪个.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

如您在此示例中所见,第一个输入没有被传递,但第二个输入被传递了。这是因为您的代码在生成器中执行到第一个yield时就停止了。因此,您传递的第一个值会丢失,因为没有代码来评估它。

让我们看另一个例子:

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

当您第二次调用.next时,会评估传入的值,并继续处理代码,直到下一个yield。在这种情况下,您执行yield input,但左侧没有任何内容,因为那实际上是JavaScript AST中的“下一行”执行。

2
如果您想要一个带参数的生成器函数,您可以使用一个返回生成器的高阶函数:
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

高阶生成器也可以很有用:

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

样例很可能是无用的,但是相同的方法可以被用来生成随机数生成器。

1
什么?那不是高阶函数。可以用微不足道的 function* myGenerator(i) { while (true) yield i++; } 替换。 - Bergi
@Bergi,你确实可以 :) 不知怎么的,我以为你不能。谢谢。"higher-order" 这个术语有什么问题吗? - esp
对我来说,你们两个的生成器都不符合高阶函数的定义。 - Bergi
确实没有返回函数...可能最初是有的。 - esp
我点赞了这个——它很棒,而且正是我所需要的,谢谢。 - mad.meesh

0
这个方法可以用来生成一个随机数,只需传入最大值即可。
function *GenerateRandomNumber(maxNo){
    while(true){
        yield Math.floor(Math.random() * maxNo);
    }
}

let randomGenerator = GenerateRandomNumber(10);
randomGenerator.next().value; // A random Number between 0 - 9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接