【JS】イテレータ関数について
時間を空けたら、自分で読み返してもよく分からなくなった。ジェネレータ、イテレータの概念は、これまで触れてこなかった身からするとなかなか難しい。
ともかく、前回に引き続き、今度はイテレータについてである。
前回のエントリ
【JS】ジェネレータ関数について - NACの勉強の経過を綴るところ
で、ジェネレータ関数について触れた。
その中で、ジェネレータ関数の戻り値が、
{ value: 4, done: false }
という形で戻ってきていることに触れ、これを「イテレータ」と呼ぶ、というところまで説明した。
調べると、イテレータとは「順番にイテレータリザルトを取り出すことのできるオブジェクト」のことだとある。
「イテレータリザルト」?
また新しい単語である。
こういう新しい単語は、順番に出てきてくれないと、こっちの処理が追いつかなくて困る。
イテレータリザルトとは、なにか。
とにかく、イテレータから順番に取り出すことができる、……つまり、「戻り値」である、と。
前回のエントリのサンプルソースで、
console.log( num .next() ); // { value: 4, done: false }
という書き方をしたが、正確に言うと、この「num」がイテレータであり、このイテレータから「.next()」で取り出された戻り値「{ value: 4, done: false }」がイテレータリザルトである。
イテレータ | プロパティ | イテレータリザルト |
---|---|---|
num | .next() | { value: 4, done: false } |
更に「{ value: 4, done: false }」細分化すると、「4」が取り出した値であり、「false 」は、「これが最後の値であるか」のboolean値である。
イテレータは「順番に値を取り出すことができるオブジェクト」であるから、「done: false」である限り、「.next()」で順番に値を呼び出すことができるわけだ。
この「イテレータ」を返すオブジェクトのことを、「イテラブルなオブジェクト」という。
ん?
なんだって?
整理整理。
イテラブル | イテレータを返すオブジェクト |
---|---|
イテレータ | 一連の複数のデータからなるオブジェクト。.next()で順番に値を返す。 |
イテレータリザルト | イテレータから返される要素のひとつひとつ。valueという値と、最後の値であるか否かの真偽値をプロパティに持つ。 |
整理されたような、されてないような。
ともかく、順番に理解していかないと、取り残される。
for~of
上記の説明を読んだ上で、気づくことがある。
「イテレータ=一連の複数のデータからなるオブジェクト」
ということは配列だってイテレータなのでは?
var arr=[0,1,2,3,4]; for(var value of arr){ console.log(value); } /* 0 1 2 3 4 */
こちらのサンプルソースは、配列から一つずつ値を取り出すもの。
配列はイテレータなので、その値をひとつずつ取り出すことができる。
しかし、取り出すのに「.next()」プロパティを使うのではなかったのか?
という疑問がわくが、そこがエレガントに簡略化されたのが、「for-of」文である。
「for-of」は、イテレータから要素を順番に取り出す機能を持っているのである。
具体的に言うと、
for(var value of arr){ console.log(value); }
とあるときに、valueはイテレータリザルトの値の部分であり、doneがtrueになるまで繰り返してくれる。
前回のサンプルソースを引き合いに出す。
function* getData(n) { n++; // 処理1 yield n; n++; // 処理2 yield n; n++; // 処理3 yield n; } var num = getData(3); // ジェネレータ作成 console.log( num .next() ); // { value: 4, done: false }
こういうソースを書いたが、これは、最初の値だけを取り出している。
それに対し、すべての値を取り出したい場合は、こう書く。
function* getData(n) { n++; // 処理1 yield n; n++; // 処理2 yield n; n++; // 処理3 yield n; } var num = getData(3); // ジェネレータ作成 for(var value of num){ console.log(value); } /* 4 5 6 */
エントリー3回に渡って長々と書いたが、結局のところ、使い勝手が良いのかどうかはいまいちわからない。
だが、概念として理解しておくことと、全く知らないのとでは、いずれ差が出るだろう。
「そういえば、あんなんあったな」と、あとで思い出せるように、心の片隅にはとどめておきたいと思う。