web-dev-qa-db-ja.com

JSジェネレータ:「収益率」と「収益率」の違いは何ですか?

function* foo() {
  yield 123
};

// - - -

function* foo() {
  return yield 123
};

両者の違いを示すことはできません。

  • 明白な違いはありますか?
  • returnをジェネレータで使用する必要がありますか?
21
Kirk Strobeck

最初に、ジェネレーターはやや複雑なトピックであるため、ここで完全な概要を説明することはできません。詳細については、Kyle Simpsonの You Do n't Know JS シリーズを強くお勧めします。 Book 5(Async&Performance)には、ジェネレーターのインとアウトに関する優れた議論があります。

あなたが与えた特定の例に!

最初に、例で記述したコードは違いなしを示しますが、if正しく実行されます。次に例を示します。

function* foo() {
  yield 123;
}

function* bar() {
  return yield 123;
}

var f = foo();
var b = bar();

f.next(); // {value: 123, done: false}
f.next(); // {value: undefined, done: true}
b.next(); // {value: 123, done: false}
b.next(); // {value: undefined, done: true}

ご覧のとおり、私は通常の関数のようにジェネレータを呼び出していません。ジェネレータ自体は、ジェネレータオブジェクト(イテレータの形式)を返します。そのイテレーターを変数に保管し、.next()関数を使用してイテレーターを次のステップに進めます(yieldまたはreturnキーワード)。

yieldキーワードを使用すると、ジェネレーターに値を渡すことができます。これにより、例の実行が異なります。これは次のようになります。

function* foo() {
  yield 123;
}

function* bar() {
  return yield 123;
}

var f = foo();
var b = bar();

// Start the generator and advance to the first `yield`
f.next(); // {value: 123, done: false}
b.next(); // {value: 123, done: false}

/** Now that I'm at a `yield` statement I can pass a value into the `yield`
 * keyword. There aren't any more `yield` statements in either function,
 * so .next() will look for a return statement or return undefined if one
 * doesn't exist. Like so:
 */
f.next(2); // {value: undefined, done: true}
b.next(2); // {value: 2, done: true}

foo()は値としてundefinedを返すのに対し、bar()は数値2を返すことに注意してください。これは、.next()呼び出しに渡す値が原因です。 returnキーワードに送信され、戻り値として設定されます。 foo()には明示的なreturnステートメントがないため、デフォルトのundefined動作が得られます。

これがお役に立てば幸いです!

26
Joshua Kleveter

違いは、最後の継続呼び出しの結果値です。

function* fooA() {
  yield 123
};
var a = fooA();
console.log(a.next(1)); // {done:false, value:123}
console.log(a.next(2)); // {done:true,  value:undefined}

function* fooB() {
  return 40 + (yield 123)
};
var b = fooB();
console.log(b.next(1)); // {done:false, value:123}
console.log(b.next(2)); // {done:true,  value:42}

ほとんどのジェネレーターはreturn値を必要としません。それらの目的は、実行中の副作用としてのバリューストリームの生成です。すべてのイテレータはこの種のものであり、for ofループによって実行された場合、結果は単に終わりを示しますが、値は破棄されます。

ただし、結果値が重要なジェネレーターもあります。非同期プロセスを説明するツールとして使用される場合(async/await promise構文のポリフィル、またはCSPなどの多くのもの)。イテラブルでyield*を使用すると、returned値も取得します。

いずれにせよ、return yieldを一緒に使用しても、あまり役に立ちません。

11
Bergi