こんにちは、ともです。
ES6からのジェネレータについて理解をまとめたいと思います。ジェネレータって使えるようになると上手いコードを書けそうですよね。
参考にしたものは下の記事です。
ジェネレーターとは
GeneratorというビルドインオブジェクトがJavaScriptには存在します。
Generatorオブジェクトのインスタンスを生成するにはジェネレータ関数によって返されます。
Generatorを利用するとより簡潔にコードを記述することが可能です。
ジェネレータ関数によりインスタンス生成
function* functionName(){}
functionに『 * 』をつけた関数がジェネレータ関数です。
試しに次のようなコードを書きました。
function* myGenerator() {
}
var mg = myGenerator();
console.log(mg);
// Out:myGenerator {<suspended>}
// __proto__: Generator
myGeneratorというジェネレータ関数の戻り値を確認したところプロトタイプがGeneratorでした。確かにGeneratorオブジェクトのインスタンスが返っています。
yieldで値を返す
function* myGenerator() {
yield 'A';//1回目のnext関数で返す
yield 'B';//2回目のnext関数で返す
yield 'C';//3回目のnext関数で返す
}
var mg = myGenerator()
console.log(mg.next()); //{ value: "A", done: false }
console.log(mg.next()); //{ value: "B", done: false }
console.log(mg.next()); //{ value: "C", done: false }
console.log(mg.next()); //{ value: undefined, done: true}
ジェネレータオブジェクトはイテレータなのでnext()
を利用できます。
- 1度目の
next()
でyield 'A'
まで実行 - 2度目の
next()
でyield 'B'
まで実行 - 3度目の
next()
でyield 'C'
まで実行 - 4度目の
next()
で{done: true}
を返し終了
となります。
つまり
- Generatorはイテレータである
- 途中で止まり再度途中から実行することが可能なメソッドが定義可能
- 繰り返し処理で作成可能なデータを関数として定義可能
ということが分かります。
途中で止まる関数
function* cheering() {
yield alert('頑張れ!');
yield alert('負けるな!');
yield alert('もう少しだ!');
}
var ch = cheering()
ch.next();
// 任意の処理
ch.next();
// 任意の処理
ch.next();
// 任意の処理
ch.next();
例は悪いかもしれませんが任意の処理を実行すると次の声援がalertされるGeneratorです。
ジェネレータでデータの定義
引数に与えた数値を割ることのできる整数値を生成するジェネレータを定義してみました。
function* canDivide(num) {
let start = 2;
while (num >= start) {
let dividedNum = num % start;
if (dividedNum === 0) {
yield start;
}
start++;
}
}
var mg = canDivide(50)
for (let val of mg) {
console.log(val)//2, 5, 10, 25, 50
}
Generatorはイテラブルなオブジェクトですのでfor...of
で値を取り出すことが可能です。正しく算出できていることが分かります。
繰り返し処理で作成できるデータなどはジェネレータでの作成すると簡潔かもしれません。
まとめ
ジェネレータを利用することで途中で止まる関数や繰り返し処理で求まるデータ群を生成することができることが分かりました。
コードの幅を広げるためにGeneratorをマスターしておきたいです。