誰かが私に説明できますか: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
の存在の検出が不十分なのはなぜですか?
3つの理由は次のとおりです。
読みやすさ。ジェネレーターは関数とはまったく異なり、その違いはすぐにわかるはずです(つまり、yieldを探すために実装全体を調べる必要はありません)。
一般性。生成せず、直接戻るだけのジェネレータを作成することは当然可能です。さらに、本体の一部をコメントアウトする(たとえば、デバッグのために)ものがジェネレーターであるかどうかを静かに変更するべきではありません。
互換性。厳密モードのみがキーワードとして「yield」を予約しましたが、すべての新機能がずさんなモードでも利用できることがES6の目標になりました(残念ながら私見ですが、それでも)。さらに、厳密なモードであっても、「歩留まり」をめぐる構文解析の微妙さが多くあります。たとえば、デフォルトの引数を検討します。
function* g(a = yield(2)) { 'use strict' }
*
がなければ、パーサーは関数の本体を見た後にのみyieldを解析する方法を決定できました。つまり、これに対処するには、無限の先読み、逆追跡、またはその他のハッキング手法が必要になります。
(1)と(2)はすでに十分な理由であることに注意してください。
(完全開示:私はEcmaScript委員会のメンバーです。)
空のジェネレーター(ボディなし)は禁止されていません。 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*
_の定義からジェネレーターであることがすぐにわかるのは、そのソースを掘り下げて歩留まりを探す必要がありません。