ES6 生成器函数中星号 (*) 的用途是什么

What's the purpose of an asterisk (*) in ES6 generator functions

谁能给我解释一下:为什么 ES6 中的生成器函数用星号标记?

例如,而不是:

function *someGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

我们可以这样写:

function someGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

甚至:

var someGenerator = () => {
    yield 1;
    yield 2;
    yield 3;
}

var someObject = {

    someGenerator() {
        yield 1;
        yield 2;
        yield 3;
    }
}            

JS 编译器可以在解析时检测到 someGenerator 包含 yield 运算符,并从该函数生成生成器。

为什么 yield 存在的检测还不够?

不禁止空发电机(没有主体);那么 unStarredFunc() 是否应该遵循生成器语义?

出于兼容性原因:

function yield(x) { return x };

function a() { 
    yield (4+1);
};

这在语法上是正确的,但调用 .next() 会导致错误,而添加星号以显式定义生成器会导致 .next().value === 5

detect that someGenerator contains yield operator at parse time

某些构造无法在解析时解析:

function someGenerator(i) { 
    if (glob) 
        return 4; 
    else 
        yield* anotherGen(i);
}

当然,从 function* 的定义中可以更简单地立即看出它是一个生成器,而无需深入研究其源代码来寻找收益。

三个原因是:

  1. 可读性。生成器与函数有很大不同,差异应该立即可见(也就是说,无需检查整个实现来寻找收益)。

  2. 普遍性。自然应该可以写出不yield的generator,直接只写return。此外,注释掉正文的一部分(例如用于调试)不应该默默地改变某物是否是生成器。

  3. 兼容性。只有严格模式保留 'yield' 作为关键字,但 ES6 的目标是所有新功能也可以在草率模式下使用(恕我直言,这是一个不幸的决定,但尽管如此)。此外,即使在严格模式下,'yield' 也有许多解析细节;例如,考虑默认参数:

    function* g(a = yield(2)) { 'use strict' }
    

    没有*,解析器只能在看到函数体后决定如何解析yield。也就是说,您需要无限前瞻、回溯或其他骇人听闻的技术来处理这个问题。

我应该注意到 (1) 和 (2) 已经足够了。

(完全披露:我是 EcmaScript 委员会的成员。)