【问题标题】:Can I use ES6's arrow function syntax with generators? (arrow notation)我可以在生成器中使用 ES6 的箭头函数语法吗? (箭头符号)
【发布时间】:2015-07-30 16:43:00
【问题描述】:

也就是说,我该如何表达

function *(next) {}

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

(我目前使用的是 Node.js v0.11.14。)

【问题讨论】:

  • 你不能。对不起。 “function* 语句(函数关键字后跟一个星号)定义了一个生成器函数。”
  • 请注意,关于此主题的讨论有些冗长 at esdiscuss.org。
  • 你希望param*=>{ }做什么?
  • 你知道function(){}和()=>{}做的不一样吗?
  • “真的是 ES6 生成器前进了 2 步,后退了 1 步吗?” - 不,generators can only step forward :-)

标签: javascript ecmascript-6 syntax generator arrow-functions


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

    生成器箭头的提案已移至 Stage 1,由 Brendan Eich 和 Domenic Denicola 担任冠军。上面提到的Asynchronous iteration是2018年的finished and implemented。

    2019 年 10 月,an official repo by Sergey Rubanov 出现,对语法和其他细节进行了更多讨论。

    【讨论】:

      【解决方案3】:

      我也有同样的问题,来到这里。看了帖子和cmets,感觉在箭头函数中使用generator好像有点模糊:

      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()。

      但是,没有像gen 或generator 这样的关键字,可惜箭头函数没有使用它。

      总结:

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

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

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


      关注@Bergi comment:

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

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

      【讨论】:

      • 也可以考虑外来选项,例如() ~> { yield 'a'; yield 'b'; }。老实说,我只是喜欢波浪号。
      • @Gershom 这就是像Perl 这样的编程语言完全出错的原因
      【解决方案4】:

      redux-saga 有一个很好的解决方法

      import { call, all } from 'redux-saga/effects';
      
      function* gen() {
         yield all([].map(() => {
            return call(....);
         }));
      }
      

      【讨论】:

      • 我们如何知道 OP 正在使用 Redux?
      【解决方案5】:

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

      【讨论】:

      • :+1: 对于双星号...这里是老派 JS 家伙。谁说你不能教老狗新把戏:joy:
      • 他们不这样做的唯一原因是因为制作解析器很困难。这是完全可能的,并且不需要在语法上妥协。
      • @JasonMcCarrell 如果他们足够关心不要让解析器变得过于复杂,那么也许 Brendan Eich 应该将 Scheme 放入浏览器中。
      【解决方案6】:

      我可以在生成器中使用 ES6 的箭头函数语法吗?

      你不能。对不起。

      根据MDN

      function* 语句(function 关键字后跟一个星号)定义了一个生成器函数。

      来自spec document(我的重点):

      function 语法被扩展为添加一个可选的* 标记:

      FunctionDeclaration: "function" "*"? Identifier "(" FormalParameterList? ")" 
        "{" FunctionBody "}"
      

      【讨论】:

      • 对我来说感觉像是一个设计缺陷。
      • @Jonathon:不。箭头函数应该是轻量级的(例如,没有.prototype)并且通常是单行的,而生成器则恰恰相反。
      • 我已经遇到过一些场景,其中我正在使用的生成器需要访问以前的 this,并且必须编写 let self = this hack 才能在生成器中访问它。词法范围 + 箭头语法会很好。不幸的是,但不完全是世界末日。
      • @Bergi 箭头函数背后的推理比这复杂得多。这与简洁无关。箭头函数不必是轻量级的——确实有一个可选的单语句体语法,但那又怎样。许多人将箭头用于除类方法之外的所有函数定义,并将function 关键字降级为语言的“坏部分”。这样做有充分的理由。对于这些人来说,缺少箭头生成器是一种令人讨厌的不一致。
      • @callum 我的意思是实例创建和调用开销方面的轻量级,而不是语法。不知道你认为他们背后的原因是什么。不,我没有看到任何充分的理由在 function 声明上使用非声明性箭头函数表达式。
      【解决方案7】:

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

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

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

      一些更快速的细节here


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

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

      yield 关键字的使用

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

      请注意,没有yield 的generators 没有意义。


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

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

      箭头函数在词法上绑定 this,在 Block 主体情况下绑定 return,以便它从立即封闭的箭头函数返回,并排除 break 和 continue 引用外部语句立即封闭的箭头函数。

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

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

      Arrow-Function 中的 Yield 将引发语义错误:http://www.ecma-international.org/

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

      【讨论】:

      • 我试图弄清楚为什么*() => { yield bla; } 不行,但async () => { await bla; } 是...
      • @CodeiSir,回复“我们不想要深度延续”,糟糕的借口。
      • 你的论点是周期性的。你说箭头函数不能是生成器,因为它们不能有 yield 关键字。但是它们不能有 yield 关键字,因为它们不能是生成器:“箭头不能是生成器,我们不想要深度延续。”
      • 这是循环推理;箭头函数不能是生成器,因为它不允许有yield 语句,也不能有yield 语句,因为它不允许作为生成器。 ?
      • 这并不能真正回答 为什么。是的,这是真的,箭头函数不能是生成器,因为它不允许包含yield,但是没有理由设计语法来允许它。设计者不希望箭头函数成为生成器的原因是什么?
      猜你喜欢
      • 2017-08-09
      • 2018-03-03
      • 2016-02-14
      • 2019-01-06
      • 1970-01-01
      • 2017-10-20
      相关资源
      最近更新 更多