NACの勉強の経過を綴るところ

個人的なコードの勉強

【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回に渡って長々と書いたが、結局のところ、使い勝手が良いのかどうかはいまいちわからない。
だが、概念として理解しておくことと、全く知らないのとでは、いずれ差が出るだろう。
「そういえば、あんなんあったな」と、あとで思い出せるように、心の片隅にはとどめておきたいと思う。