简体   繁体   English

我可以在生成器中使用 ES6 的箭头 function 语法吗? (箭头符号)

[英]Can I use ES6's arrow function syntax with generators? (arrow notation)

That is, how do I express也就是我怎么表达

function *(next) {}

with arrow syntax?用箭头语法? I've tried all the combinations I could think of, and I can't find any documentation on it.我已经尝试了所有我能想到的组合,但找不到任何文档。

(I am currently using Node.js v0.11.14.) (我目前使用的是 Node.js v0.11.14。)

Can I use ES6's arrow function syntax with generators?我可以在生成器中使用 ES6 的箭头函数语法吗?

You can't.你不能。 Sorry.对不起。

According to MDN根据MDN

The function* statement ( function keyword followed by an asterisk) defines a generator function. function*语句( function关键字后跟一个星号)定义了一个生成器函数。

From a spec document (my emphasis):规范文件(我的重点):

The function syntax is extended to add an optional * token:函数语法被扩展为添加一个可选的*标记:

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

The difference between Inline-functions and Arrow-functions内联函数和箭头函数的区别

First of all Arrow-functions () => {} are not made to replace Inline-functions function(){} and they are different.首先, 箭头函数() => {}不是用来代替内联函数function(){} ,它们是不同的。 Inline-Functions are simply Functions, so the question is what the difference between Arrow-functions and Inline-Functions are.内联函数只是函数,所以问题是箭头函数和内联函数之间的区别是什么。

An arrow function expression (also known as arrow function) has a shorter syntax compared to function expressions and does not bind its own this , arguments , super , or new.target ).与函数表达式相比,箭头函数表达式(也称为箭头函数)具有更短的语法,并且不绑定自己的thisargumentssupernew.target )。 Arrow functions are always anonymous.箭头函数总是匿名的。

Some more quick details here 这里有一些更快速的细节


Why Arrow-function can not be used as generators为什么箭头函数不能用作生成器

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

Use of the yield keyword使用 yield 关键字

The yield keyword may not be used in an arrow function's body (except when permitted within functions further nested within it).不能在箭头函数的主体中使用yield关键字(除非允许在进一步嵌套在其中的函数中使用)。 As a consequence, arrow functions cannot be used as generators.因此,箭头函数不能用作生成器。

Note that generators without yield don't make sense.请注意,没有yield 生成器没有意义。


Why Arrow-function can not use yield为什么箭头函数不能使用yield

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

Arrow functions bind this lexically, bind return in the Block body case so it returns from the immediately enclosing arrow function, and preclude break and continue from referencing statements outside the immediately enclosing arrow function.箭头函数在词法上绑定this ,在Block主体情况下绑定return以便它从直接封闭的箭头函数返回,并阻止breakcontinue引用直接封闭的箭头函数之外的语句。

The Identifier primary expression arguments may not be used in an arrow function's body (whether expression or block form).标识符主要表达式arguments不能用于箭头函数的主体(无论是表达式还是块形式)。

Likewise, yield may not be used in an arrow function's body.同样, yield不能用于箭头函数的主体。 Arrows cannot be generators and we do not want deep continuations.箭头不能是生成器,我们不想要深度延续。

Yield in an Arrow-Function will throw Semantic Error: http://www.ecma-international.org/箭头函数中的产量将引发语义错误: http : //www.ecma-international.org/

In the End the reason is in the deep complexity in the implementation of ECMA6.归根结底,原因在于 ECMA6 实施的深度复杂性。 C# does not allow this as well for somewhat similar reasons .出于类似的原因, C# 也不允许这样做。

In addition to the discussion on esdiscuss.org and the Ecma TC39 committee ES6 meeting notes from November 2013 mentioned above, generator arrows were revisited in two September 2016 ES7 meetings [1] [2] .除了上面提到的esdiscuss.org上的讨论和2013 年 11 月的 Ecma TC39 委员会 ES6 会议记录之外,在 2016 年 9 月的两次 ES7 会议中重新讨论了生成器箭头[1] [2] After a discussion about pros and cons of various syntax (mainly =*> and =>* ) and a lack of justifications and use cases for this feature, they came to the conclusion that:在讨论了各种语法(主要是=*>=>* )的优缺点以及此功能缺乏理由和用例后,他们得出的结论是:

  • There is some interest from the committee, but concern that the feature does not pull its weight for adding a new piece of syntax委员会有一些兴趣,但担心该功能不会为添加新语法而发挥作用
  • Plan to revisit on Day 3 to see if we can get =>* to stage 0 at least, as part of [Domenic Denicola]'s async iteration proposal计划在第 3 天重新访问,看看我们是否可以让=>*至少进入第 0 阶段,作为 [Domenic Denicola] 的异步迭代提案的一部分

The proposal for generator arrows was moved to Stage 1 with Brendan Eich and Domenic Denicola as champions.发电机箭头的提议被移至第一阶段,Brendan Eich 和 Domenic Denicola 作为冠军。 Asynchronous iteration mentioned above was finished and implemented in 2018.上述异步迭代于2018年完成并实现

In Oct 2019 an official repo by Sergey Rubanov appeared with more discussion about syntax and other details. 2019 年 10 月,谢尔盖·鲁巴诺夫 (Sergey Rubanov) 的官方回购出现了更多关于语法和其他细节的讨论。

I was also having the same question and came here.我也有同样的问题,来到这里。 After reading the posts and comments, I felt using generator in an arrow function seems to be vague:阅读帖子和评论后,我觉得在箭头函数中使用生成器似乎很模糊:

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

This is what may be the big reason they didn't implement generator in relation with arrow function.这可能是他们没有实现与箭头函数相关的生成器的重要原因。


But, if I were one of them, I could have thought like this:但是,如果我是其中之一,我可能会这样想:

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

This feels just like we have asynchronous function:这感觉就像我们有异步函数:

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

Because, with normal function the async keyword exist, so arrow function is utilizing it - async () => is likely to seem async function() .因为,在普通函数中存在async关键字,所以箭头函数正在使用它 - async () =>可能看起来是async function()

But, there's no keyword like gen or generator and alas arrow function is not using it.但是,没有像gengenerator这样的关键字,唉箭头函数也没有使用它。

To conclude:总结:

Even if they wish to implement the generator in the arrow function, I think they need to re-think about generator syntax in core js:即使他们希望在箭头函数中实现生成器,我认为他们需要重新考虑核心js中的生成器语法:

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

And this will be a big blunder.这将是一个大错误。 So, keeping arrow function out from the generator, is pretty cool.因此,将箭头函数排除在生成器之外,非常酷。


Following @Bergi comment :以下@Bergi 评论

No. Arrow functions are supposed to be light-weight (and don't have a .prototype for example) and often one-liners, while generators are pretty much the opposite.不。箭头函数应该是轻量级的(例如没有 .prototype)并且通常是单行的,而生成器则恰恰相反。

I will say that generator purpose to use is run-stop-run and so I don't think we need to care about prototype, lexical this, etc.我会说生成器的使用目的是运行-停止-运行,所以我认为我们不需要关心原型、词法 this 等。

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

I know that this is very late, but another possible reason could be syntax.我知道这已经很晚了,但另一个可能的原因可能是语法。 maybe (*() => {}) works, but what about (9 ** () => {}) ?也许(*() => {})有效,但是(9 ** () => {})呢? Is that 9 to the power of an arrow function, returning NaN , or is it 9 times a generator arrow function, also returning NaN ?是箭头函数的 9 次幂,返回NaN ,还是生成器箭头函数的 9 倍,也返回NaN It could be done with some alternative syntax, like =>* as mentioned by another answer here, but maybe there was a desire to preserve the consistency of the generator function syntax (eg. function* () {} and { *genMethod() {} } ) when it was being implemented.可以使用一些替代语法来完成,例如此处另一个答案中提到的=>* ,但可能希望保持生成器函数语法的一致性(例如function* () {}{ *genMethod() {} } ) 实施时。 Not too much of an excuse, but a reason for it.不是太多的借口,而是一个理由。

You can, but not really in a nice way.你可以,但不是很好。 It's not shorter and does not look that pretty.它不短,看起来也不那么漂亮。 Check this out:看一下这个:

function* iterable(arg): Iterable<never> {
    yield* [];
}

async function* asyncIterable(arg): AsyncIterable<never> {
    yield* [];
}

const arrowIterable = arg => {
    return {
        *[Symbol.iterator]() {
            yield* [];
        },
    };
};

const arrowAsyncIterable = arg => {
    return {
        async *[Symbol.asyncIterator]() {
            yield* [];
        },
    };
};

This works because an iterable is basically an object with the Symbol.iterator or Symbol.asyncIterator set to an iterator.这是可行的,因为可迭代对象基本上是一个 object,其中Symbol.iteratorSymbol.asyncIterator设置为一个迭代器。 A generator is an iterator!生成器是迭代器!

Enjoy!享受!

There is a nice workaround with redux-saga redux-saga 有一个很好的解决方法

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

function* gen() {
   yield all([].map(() => {
      return call(....);
   }));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM