web-dev-qa-db-ja.com

ES6ジェネレーター関数のアスタリスク(*)の目的は何ですか

誰かが私に説明できますか: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コンパイラーは、someGeneratoryield演算子を含むことを解析時に検出し、この関数からジェネレーターを作成できます。

yieldの存在の検出が不十分なのはなぜですか?

43
alexpods

3つの理由は次のとおりです。

  1. 読みやすさ。ジェネレーターは関数とはまったく異なり、その違いはすぐにわかるはずです(つまり、yieldを探すために実装全体を調べる必要はありません)。

  2. 一般性。生成せず、直接戻るだけのジェネレータを作成することは当然可能です。さらに、本体の一部をコメントアウトする(たとえば、デバッグのために)ものがジェネレーターであるかどうかを静かに変更するべきではありません。

  3. 互換性。厳密モードのみがキーワードとして「yield」を予約しましたが、すべての新機能がずさんなモードでも利用できることがES6の目標になりました(残念ながら私見ですが、それでも)。さらに、厳密なモードであっても、「歩留まり」をめぐる構文解析の微妙さが多くあります。たとえば、デフォルトの引数を検討します。

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

    *がなければ、パーサーは関数の本体を見た後にのみyieldを解析する方法を決定できました。つまり、これに対処するには、無限の先読み、逆追跡、またはその他のハッキング手法が必要になります。

(1)と(2)はすでに十分な理由であることに注意してください。

(完全開示:私はEcmaScript委員会のメンバーです。)

55

空のジェネレーター(ボディなし)は禁止されていません。 unStarredFunc()はジェネレータのセマンティクスに従うべきですか?

互換性の理由から:

_function yield(x) { return x };

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

これは構文的には正しいですが、.next()を呼び出すとエラーが発生し、アスタリスクを追加してジェネレータを明示的に定義すると.next().value === 5が発生します

解析時にsomeGeneratorにyield演算子が含まれていることを検出する

一部の構成体は解析時に解決できません。

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

そしてもちろん、_function*_の定義からジェネレーターであることがすぐにわかるのは、そのソースを掘り下げて歩留まりを探す必要がありません。

7
Alex K.