【ECMAScript2015(ES6)】後で猫に教えてあげたいES6の「Generators(ジェネレーター)とIterator(イテレータ)」
昨日はSymbol(シンボル)でしたが、今日はGeneratorsとIterator。
babel立ち上げてコード確認しながらやりました。
ジェネレータってなにかって再帰処理を簡単にしてくれるものなんですね。
そのイテレータオブジェクトを返す関数がジェネレータ
ジェネレータを扱うにはイテレータを理解する必要があるようです。
イテレータを理解する
イテラタブルなオブジェクト・・・イテレータを返すオブジェクト
イテラブルなオブジェクトとは以下です
- Array
- String
- Iterator
- ジェネレータ関数から生成されるジェネレータ
- argument
- Map
- Set
- TypedArray(型付き配列みたいです。わからないのでこんどまとめます)
ArrayとStringってイテレータブルだったのかと思って
["a","b"].next();やってもだめですよ。
それには
["a","b"][Symbole.iterator]();
としてIteratorをつくります。
StringとArrayがイテラブルなオブジェクトであることを確認する
イテレータ・・・イテレーティブリザルトを返すオブジェクト。nextメソッドを持つ
イテレーティブリザルト・・・valueとdoneプロパティをもつこのような{value: 1, done: false}オブジェクト
自作イテラブルなオブジェクト
[code lang="javascript"]
var obj = {}; // イテラブルなオブジェクト
obj[Symbol.iterator] = function(){//イテレータを返す関数を代入
var iterator = {}; // イテレータ
var num = 1;
iterator.next = function(){//next実行してリザルトを返す関数を代入
var iteratorResult = (num <= 10)
? { value: num++, done: false }
: { value: undefined, done: true };
return iteratorResult; // イテレータリザルトを返す
};
return iterator;//イテレータを返す
};
[/code]
実際に下の様に値を動かします
[code lang="javascript"]
console.log("実験1")
var arry = [4, 3, 2];
for(var i of arry) console.log(i)
//for/ofはイテレータオブジェクトのdoneがfalseの間next()を実行してvalueを渡す
//4
//3
//2
//for ofの処理は
//1 iteratorオブジェクトからイテレータを取り出す
//2 イテレータのnextメソッドでイテレータリザルトを取り出す
//3 イテレータリザルトのdoneプロパティがfalseならconsole.log(i)を実行する
//4 以後nextを実行、done === trueになるまで繰り返す
<h4>ジェネレータを作成して値を動かす</h4>
ジェネレータとはイテレータを返す関数を簡単に書くもの。
console.log(`
${'実験3'}
`);
//簡単な説明
//1・ジェネレーター関数を作成
function* gf(){
yield 1 //イールドというみたいです「支払う」意味
yield 2
}
//2・ジェネレータを作成
const g = gf();//Iteratorを取得
//3・イテレータリザルトを取得
//方法1
//ジェネレータが持つnextメソッドを利用
console.log(g.next())//{"value":1,"done":false}
console.log(g.next())//{"value":2,"done":false}
console.log(g.next())//{"done":true}
//NOTE
//イテレータリザルト
//{"value":1,"done":false}
//こちらのdoneがfalseの場合valueが返る→処理される
//{"done":true}
//とされイテレータ処理するものがないことが確認される
//方法2
//for/ofでいっぺんに処理する。next処理がされる
for(var v of g) console.log(v);//イテレータを渡している
//1
//2
//ジェネレータ自体がイテラブルオブジェクトなのでこのままわたしてもok
//for(var v of gf()) console.log(v)
/////////////////////////////
console.log(`
${'実験4'}
`);
//一回目の処理と二回目の戻り値を変える
function* gfu2(n){
n++
yield n
n *= 3//2回目の処理ではここから始まり、nは1回目の処理が終わっている(5が代入されている)
yield n//15を返す
}
const gg = gfu2(4);
console.log("実験4-1",gg.next().value);//1回目の実行
//実験4-1 5
console.log("実験4-2",gg.next().value);//2回目の実行
//実験4-2 15
/////////////////////////////
console.log(`
${'実験5'}
`);
//1~20迄を出力する
function* gfu3(from, to){
while (from <= to) yield from++
}
for(var i of gfu3(1, 10)){
console.log(i);
}
/////////////////////////////
console.log(`
${'実験6'}
`);
//呼び出し側の値を受け取る
function* gfu4(){
var num = yield [10,20,30]//numは2回目next()実行時の仮引数になる
var num2 = yield 1 + num//num2は3回目next()実行時の仮引数になる
yield 2 + num2
yield num + num2
}
var g4 = gfu4();
console.log("実験6-1",g4.next().value);
//実験2-1 [10,20,30]
console.log("実験6-2",g4.next(4).value);//値を渡す
//実験2-2 5
console.log("実験6-3",g4.next(10).value);
//実験2-3 12
console.log("実験6-4",g4.next().value);
//実験2-4 14
/////////////////////////////
console.log(`
${'Tips'}
`);
//もしfor/of中にindexがほしいならforEach
//もしくはentries()
const arry3 = ["one", "two", "three"]
for(const [key, value] of arry3.entries()) {
console.log(key, value);
}
//0 one
//1 two
//2 three
//またはArray.indexOf();
const arry4 = ["one", "two", "three"]
for(const i of arry4) {
console.log(i);
console.log(arry4.indexOf(i));
}
//"one"
//0
//"two"
//1
//"three"
//2
/////////////////////////////
console.log(`
${'実験7'}
`);
function* gfun6(){
yield "mo"
yield* ["ri","ta"]
}
const g6 = gfun6();
console.log(g6.next().value);//mo
console.log(g6.next().value);//ri
console.log(g6.next().value);//ta
/////////////////////////////
//【WIP】疲れた。。。休憩します
console.log([...gfun6()]);
/////////////////////////////
[/code]