314

也就是我怎么表达

function *(next) {}

用箭头语法?我已经尝试了所有我能想到的组合,但我找不到任何关于它的文档。

(我目前正在使用 Node.js v0.11.14。)

4

7 回答 7

296

Can I use ES6's arrow function syntax with generators?

You can't. Sorry.

According to MDN

The function* statement (function keyword followed by an asterisk) defines a generator function.

From a spec document (my emphasis):

The function syntax is extended to add an optional * token:

FunctionDeclaration: "function" "*"? Identifier "(" FormalParameterList? ")" 
  "{" FunctionBody "}"
于 2014-12-26T20:03:31.043 回答
154

内联函数和箭头函数的区别

首先,箭头函数 () => {}不是用来代替内联函数的function(){},它们是不同的。内联函数只是函数,所以问题是箭头函数和内联函数之间的区别是什么。

与函数表达式相比,箭头函数表达式(也称为箭头函数)具有更短的语法,并且不绑定自己的thisargumentssupernew.target)。箭头函数始终是匿名的。

这里有一些更快速的细节


为什么箭头函数不能用作生成器

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

使用 yield 关键字

yield关键字不能用在箭头函数的主体中(除非允许在进一步嵌套的函数中使用)。因此,箭头函数不能用作生成器。

请注意,没有生成器没有yield意义。


为什么箭头函数不能使用yield

http://tc39wiki.calculist.org/es6/arrow-functions/

箭头函数在this词法上绑定return,在Block主体情况下绑定,因此它从直接封闭的箭头函数返回,并排除breakcontinue引用直接封闭的箭头函数之外的语句。

标识符主表达式arguments不能用于箭头函数的主体(无论是表达式还是块形式)。

同样,yield不能在箭头函数的主体中使用。箭头不能成为生成器,我们不希望深度延续。

箭头函数的产量将引发语义错误: http: //www.ecma-international.org/

归根结底,原因在于 ECMA6 实现的深度复杂性。由于类似的原因,C# 也不允许这样做。

于 2015-12-05T16:42:29.097 回答
51

除了上面提到的esdiscuss.org上的讨论和2013 年 11 月的 Ecma TC39 委员会 ES6 会议记录之外,在 2016 年 9 月的两次 ES7 会议中重新讨论了生成器箭头[1] [2]=*>在讨论了各种语法(主要是and )的优缺点以及=>*缺乏对此功能的理由和用例之后,他们得出的结论是:

  • 委员会有一些兴趣,但担心该功能不会因为添加新语法而发挥作用
  • 作为 [Domenic Denicola] 的异步迭代提案的一部分,计划在第 3 天重新访问,看看我们是否=>*至少可以进入第 0 阶段

生成器箭头的提案被移至第 1 阶段,由 Brendan Eich 和 Domenic Denicola 作为冠军。上述异步迭代已于 2018 年完成并实施

2019 年 10 月,Sergey Rubanov 的官方 repo出现了,其中包含更多关于语法和其他细节的讨论。

于 2016-12-07T11:03:29.740 回答
11

我也有同样的问题,来到这里。看完帖子和评论后,我觉得在箭头函数中使用生成器似乎很模糊:

const generator = () => 2*3; // * implies multiplication
// so, this would be a confusing
const generator = () =>* something; // err, multiplying?
const generator = () =*> ... // err, ^^
const generator = ()*=> ... // err, *=3, still multiplying?
const generator=*()=> ... // err, ^^
const generator = *param => ... //err, "param" is not fixed word

这可能是他们没有实现与箭头函数相关的生成器的主要原因。


但是,如果我是他们中的一员,我可能会这样想:

const generator = gen param => ... // hmm, gen indicates a generator
const generator = gen () => ... // ^^

这感觉就像我们有异步函数:

const asyncFunction = async () => ... // pretty cool

因为,在普通函数中存在async关键字,所以箭头函数正在使用它 -async () =>可能看起来async function().

但是,没有类似genor的关键字generator,可惜箭头函数没有使用它。

总结:

即使他们希望在箭头函数中实现生成器,我认为他们需要重新考虑核心 js 中的生成器语法:

generator function myfunc() {}
// rather than
function* myfunc() {} // or, function *myfunc() {}

这将是一个大错误。因此,将箭头函数从生成器中排除出来是非常酷的。


@Bergi 评论之后:

不。箭头函数应该是轻量级的(例如没有 .prototype)并且通常是单行的,而生成器则恰恰相反。

我会说生成器的使用目的是运行-停止-运行,所以我认为我们不需要关心原型、词法 this 等。

于 2019-02-01T15:57:50.670 回答
6

现在你不能,但将来你可能会因为 TC39 在 2019 年 10 月发布相同的提案,这是在第 1 阶段。

于 2020-02-24T17:08:03.657 回答
3

我知道这已经很晚了,但另一个可能的原因可能是语法。也许(*() => {})有效,但是呢(9 ** () => {})?是箭头函数的 9 次方,返回NaN,还是生成器箭头函数的 9 倍,也返回NaN?可以使用一些替代语法来完成,就像=>*这里的另一个答案所提到的那样,但也许希望在实现生成器函数语法(例如function* () {}and { *genMethod() {} })时保持其一致性。不是太多的借口,而是一个理由。

于 2018-04-23T17:25:28.593 回答
-7

There is a nice workaround with redux-saga

import { call, all } from 'redux-saga/effects';

function* gen() {
   yield all([].map(() => {
      return call(....);
   }));
}
于 2018-08-11T12:58:58.500 回答