Generator について
■ Generator について
ECMAScript 6 世代の機能です。
■ジェネレーターとは?
ジェネレーターは、生成者を意味します。
ジェネレーター関数と呼ばれる命令文を記述し、データを順番に生成できます。
ジェネレーター関数は、実行を途中で中断し、結果を得る事ができます。
中断した場所から、実行を再開する事もできます。
Iterator と互換性があり、同じ方法で、順番にデータを列挙できます。
Generator 関数について
■ジェネレーター関数について
■ジェネレーター関数を宣言する
function* 演算子を使用します。
ジェネレーター関数を宣言する
// ------------------------------------------------------------
// ジェネレーター関数を宣言する
// ------------------------------------------------------------
function* GeneratorFunc ( argument1 , argument2 ){
yield 0;
}
■ジェネレーター関数を動的に作成する
function* リテラルを使用します。
ジェネレーター関数を動的に作成する
// ------------------------------------------------------------
// ジェネレーター関数を動的に作成する
// ------------------------------------------------------------
var generator_func = function* ( argument1 , argument2 ){
yield 0;
};
■ Generator オブジェクトを生成する
■ Generator オブジェクトを生成する
ジェネレーター関数に対して、関数呼び出し演算子 () を使用します。
引数から、ジェネレーター関数に値を渡す事もできます。
■作成例
Generator オブジェクトを作成する
// ------------------------------------------------------------
// ジェネレーター関数を宣言する
// ------------------------------------------------------------
function* GeneratorFunc ( argument1 , argument2 ){
yield 0;
}
// ------------------------------------------------------------
// 新しい Generator オブジェクトを生成する
// ------------------------------------------------------------
var generator0 = GeneratorFunc();
var generator1 = GeneratorFunc( "引数1" , "引数2" );
// ------------------------------------------------------------
// 出力テスト
// ------------------------------------------------------------
console.log(generator0);
console.log(generator1);
■ジェネレーター関数を実行するには?
Generator オブジェクトの、next() メソッドを使用します。
■ yield 文について
■ yield を含む構文例
yield を含む構文例
function* 関数名 ( 引数 ){
var 引数 = yield 戻り値;
var 引数 = yield 戻り値;
var 引数 = yield 戻り値;
}
■関数の実行を中断して結果を得る
yield 文まで実行されると、いったん中断されます。
ジェネレーターは、suspended な状態に変化します。
結果は、next() メソッドの戻り値となります。
yield 文による戻り値を確認する
// ------------------------------------------------------------
// ジェネレーター関数
// ------------------------------------------------------------
function* GeneratorFunc(){
yield "aaa";
yield "bbb";
yield "ccc";
}
// ------------------------------------------------------------
// Generator オブジェクトを作成する
// ------------------------------------------------------------
var generator = GeneratorFunc();
// ------------------------------------------------------------
// ジェネレータを順番に実行して結果を得る
// ------------------------------------------------------------
console.log( generator.next() ); // { done:false , value:"aaa" }
console.log( generator.next() ); // { done:false , value:"bbb" }
console.log( generator.next() ); // { done:false , value:"ccc" }
console.log( generator.next() ); // { done:true , value:undefined }
console.log( generator.next() ); // { done:true , value:undefined }
■引数から値を渡して、関数の実行を再開する
もう一度、next() メソッドを呼び出します。
引数から、値を渡す事もできます。
前回中断した yield 文の位置から、実行は再開されます。
yield 文と next() メソッドの相互関係を確認する
// ------------------------------------------------------------
// ジェネレーター関数
// ------------------------------------------------------------
function* GeneratorFunc( args ){
console.log(args); // "--引数--"
var result0 = yield "aaa";
console.log(result0); // "あああ"
var result1 = yield "bbb";
console.log(result1); // "いいい"
var result2 = yield "ccc";
console.log(result2); // "ううう"
}
// ------------------------------------------------------------
// Generator オブジェクトを作成する
// ------------------------------------------------------------
var generator = GeneratorFunc("--引数--");
// ------------------------------------------------------------
// ジェネレータを順番に実行して結果を得る
// ------------------------------------------------------------
var value0 = generator.next();
var value1 = generator.next("あああ");
var value2 = generator.next("いいい");
var value3 = generator.next("ううう");
// 出力テスト
console.log(value0); // { done:false , value:"aaa" }
console.log(value1); // { done:false , value:"bbb" }
console.log(value2); // { done:false , value:"ccc" }
console.log(value3); // { done:true , value:undefined }
■ yield* 文について
戻り値として、Iterable なオブジェクトを指定できます。
この場合、引数から値を渡す事はできません。
yield* 文による戻り値を確認する
// ------------------------------------------------------------
// ジェネレーター関数
// ------------------------------------------------------------
function* GeneratorFunc(){
yield* [ "aaa" , "bbb" , "ccc" ];
yield* "あいう";
}
// ------------------------------------------------------------
// Generator オブジェクトを作成する
// ------------------------------------------------------------
var generator = GeneratorFunc();
// ------------------------------------------------------------
// ジェネレータを順番に実行して結果を得る
// ------------------------------------------------------------
console.log( generator.next() ); // { done:false , value:"aaa" }
console.log( generator.next() ); // { done:false , value:"bbb" }
console.log( generator.next() ); // { done:false , value:"ccc" }
console.log( generator.next() ); // { done:false , value:"あ" }
console.log( generator.next() ); // { done:false , value:"い" }
console.log( generator.next() ); // { done:false , value:"う" }
console.log( generator.next() ); // { done:true , value:undefined }
console.log( generator.next() ); // { done:true , value:undefined }
■ return 文について
ジェネレーターを、closed な状態に変化させます。
戻り値を指定できますが、結果は特殊です。
for..of 文などを使った場合、列挙に含まれません。
return 文による戻り値を確認する
// ------------------------------------------------------------
// ジェネレーター関数
// ------------------------------------------------------------
function* GeneratorFunc(){
yield "aaa";
yield "bbb";
yield "ccc";
return "ddd";
}
// ------------------------------------------------------------
// Generator オブジェクトを作成する
// ------------------------------------------------------------
var generator0 = GeneratorFunc();
var generator1 = GeneratorFunc();
// ------------------------------------------------------------
// ジェネレータを順番に実行して結果を得る
// ------------------------------------------------------------
console.log( generator0.next() ); // { done:false , value:"aaa" }
console.log( generator0.next() ); // { done:false , value:"bbb" }
console.log( generator0.next() ); // { done:false , value:"ccc" }
console.log( generator0.next() ); // { done:true , value:"ddd" }
console.log( generator0.next() ); // { done:true , value:undefined }
console.log( generator0.next() ); // { done:true , value:undefined }
// ------------------------------------------------------------
// for..of 文を使って、データを列挙する
// ------------------------------------------------------------
var value;
for(value of generator1){
console.log( value );
}
Generator オブジェクトについて
■ジェネレーターを実行して結果を得る
■ ジェネレーターを実行して結果を得る
next() メソッドを使用します。
next() メソッドを、何度も呼び出す事で、値情報を順番に取り出せます。
Generator.next( value ) :IteratorResult
第01引数(略可) | * | 中断した yield 文に渡す値を指定する(suspended の状態である場合) |
戻り値 | IteratorResult | 新しい IteratorResult オブジェクトが得られる。 |
■IteratorResult オブジェクトについて
プロパティ | 型 | 解説 |
done | Boolean | 列挙が最後尾まで完了したなら true |
value | * | 今回の値情報を取得する |
■ yield 文との連携について
詳しくは、こちらで解説しています。
■ジェネレーターを閉じて結果を得る
return() メソッドを使用します。
ジェネレーターを、closed な状態に変化させます。
Generator.return( value ) :IteratorResult
第01引数(略可) | * | 最後の値情報を指定する |
戻り値 | IteratorResult | 新しい IteratorResult オブジェクトが得られる。 |
■使用例
return() メソッドの動作を確認する
// ------------------------------------------------------------
// ジェネレーター関数
// ------------------------------------------------------------
function* GeneratorFunc(){
yield "aaa";
yield "bbb";
yield "ccc";
}
// ------------------------------------------------------------
// Generator オブジェクトを作成する
// ------------------------------------------------------------
var generator = GeneratorFunc();
// ------------------------------------------------------------
// ジェネレータを順番に実行して結果を得る
// ------------------------------------------------------------
console.log( generator.next() ); // { done:false , value:"aaa" }
console.log( generator.next() ); // { done:false , value:"bbb" }
// ------------------------------------------------------------
// ジェネレータを閉じる
// ------------------------------------------------------------
var result = generator.return("ddd");
// 出力テスト
console.log( result ); // { done:true , value:undefined }
// ------------------------------------------------------------
// 閉じられたか確認する
// ------------------------------------------------------------
console.log( generator.next() ); // { done:true , value:undefined }
console.log( generator.next() ); // { done:true , value:undefined }
■ジェネレーターにエラーをスローする
throw() メソッドを使用します。
ジェネレーターを、closed な状態に変化させます。
Generator.throw( exception ) :Void
第01引数(略可) | Error | Error オブジェクトなどを指定 |
戻り値 | Void | なし |
■使用例
throw() メソッドの動作を確認する
// ------------------------------------------------------------
// ジェネレーター関数
// ------------------------------------------------------------
function* GeneratorFunc(){
yield "aaa";
yield "bbb";
yield "ccc";
}
// ------------------------------------------------------------
// Generator オブジェクトを作成する
// ------------------------------------------------------------
var generator = GeneratorFunc();
// ------------------------------------------------------------
// ジェネレータを順番に実行して結果を得る
// ------------------------------------------------------------
console.log( generator.next() ); // { done:false , value:"aaa" }
console.log( generator.next() ); // { done:false , value:"bbb" }
// ------------------------------------------------------------
// ジェネレータにエラーをスローする
// ------------------------------------------------------------
try{
// Error オブジェクトを作成
var error_obj = new Error("ddd");
// 例外エラーを投げる
generator.throw(error_obj);
}catch(e){
console.log(e); // "ddd"
}
// ------------------------------------------------------------
// 閉じられたか確認する
// ------------------------------------------------------------
console.log( generator.next() ); // { done:true , value:undefined }
console.log( generator.next() ); // { done:true , value:undefined }
■Generator を使ってデータを列挙する
こちらで解説しています。
Generator は、Iterator の仕様を満たします。
■値情報を順番に列挙する例(Iterator オブジェクト)
while 文を使って、値情報を順番に取得する
// ------------------------------------------------------------
// ジェネレーター関数
// ------------------------------------------------------------
function* GeneratorFunc(){
yield* ["aaa" , "bbb" , "ccc" , "ddd" , "eee"];
}
// ------------------------------------------------------------
// Generator オブジェクトを作成する
// ------------------------------------------------------------
var generator = GeneratorFunc();
// ------------------------------------------------------------
// 値情報を順番に列挙する
// ------------------------------------------------------------
var result = generator.next();
while(!(result.done)){
console.log( result.value );
result = generator.next();
}
■値情報を順番に列挙する例(for..of 文)
for..of 文を使って、値情報を順番に取得する
// ------------------------------------------------------------
// ジェネレーター関数
// ------------------------------------------------------------
function* GeneratorFunc(){
yield* ["aaa" , "bbb" , "ccc" , "ddd" , "eee"];
}
// ------------------------------------------------------------
// Generator オブジェクトを作成する
// ------------------------------------------------------------
var generator = GeneratorFunc();
// ------------------------------------------------------------
// 値情報を順番に列挙する(Iterable なオブジェクトを指定)
// ------------------------------------------------------------
var value;
for(value of generator){
console.log( value );
}
■すべての値情報をまとめて取得する例(Map オブジェクトを取得)
ジェネレーターから、Map オブジェクトを生成する
// ------------------------------------------------------------
// ジェネレーター関数(オブジェクトから [ "キー" , 値 ] を列挙)
// ------------------------------------------------------------
function* Object_Entries(obj){
var key;
for(key in obj){
var value = obj[key];
yield [ key , value ];
}
};
// ------------------------------------------------------------
// 適当なオブジェクトを用意
// ------------------------------------------------------------
var dictionary = {
"aaa":"あ",
"bbb":"い",
"ccc":"う",
"ddd":"え",
"eee":"お"
};
// ------------------------------------------------------------
// ジェネレーターを生成
// ------------------------------------------------------------
var generator = Object_Entries(dictionary);
// ------------------------------------------------------------
// ジェネレーターから、Map オブジェクトを生成する
// ------------------------------------------------------------
var map = new Map(generator);
// 出力テスト
console.log(map); // { "aaa":"あ" , "bbb":"い" , "ccc":"う" , "ddd":"え" , "eee":"お" }