ジェネレーター関数で反復処理(function*, yield, next)

JavaScriptのコードで「yield」や「next()」などの記述を見かけて、どういった動作をするのか不思議に思ったことはないでしょうか?ここでは、function*構文でジェネレータ関数を実装して、ジェネレータの動作確認を行います。

動作確認
( yield, nextメソッドの動作を理解する )

nodeで動作確認します。app.jsというファイルを作成して、以下処理を記述します。

function* generatorFn1() {
  console.log('generatorFn1 1')
  yield 100
  console.log('generatorFn1 2')
  yield 200
  console.log('generatorFn1 3')
}

const generator1 = generatorFn1()

console.log('start')
console.log('next 1')
console.log(generator1.next())
console.log('next 2')
console.log(generator1.next())
console.log('next 3')
console.log(generator1.next())
console.log('next 4')
console.log(generator1.next())
console.log('end')

function*構文ジェネレータ関数 を実装でき、ジェネレータ関数から取得したオブジェクトを ジェネレータ といいます。上記例でいうと、ジェネレータ関数generatorFn1() であり、 ジェネレータgenerator1 です。

以下、実行結果です。

$ node app.js 
start
next 1
generatorFn1 1
{ value: 100, done: false }
next 2
generatorFn1 2
{ value: 200, done: false }
next 3
generatorFn1 3
{ value: undefined, done: true }
next 4
{ value: undefined, done: true }
end

ジェネレータの nextメソッド を呼び出すたびに、ジェネレータ関数の yield が記述された箇所まで実行されています。

nextメソッドの戻り値は valueプロパティyield で指定した値が格納されており、doneプロパティ にジェネレータ関数の処理が全て完了したか判定するためのboolean値が格納されています。

for of構文でジェネレータを利用

ジェネレータは for of構文 で利用できます。app.jsというファイルを作成して、以下処理を記述します。

function* indexGeneratorFn(from, to) {
  let index = from
  while (index <= to) {
    yield index++
  }
}

const indexGenerator = indexGeneratorFn(5, 10)
for (const index of indexGenerator) {
  console.log(index)
}

以下、実行結果です。

$ node app.js 
5
6
7
8
9
10

参考