イテレータ・ジェネレータ(ついでにシンボルもちょっとだけ)覚えたことメモ

tuitui.hatenablog.com

↑昨年イテレータについて後日読もうと思っていたんですが、ようやくその「後日」が来ました。
イテレータ・ジェネレータ(ついでにシンボルもちょっとだけ)について覚えたことをメモ。
自分でIterableなオブジェクトを書いてもいいし、arrayやstringにはそもそも備わっているということで
なんだ〜となりました。もっと早くちゃんと読んでおけばよかったなと思った次第です。  

Iterationについて

繰り返し処理を行うための決まりに従った実装。
繰り返し処理を適用したときの挙動 → Iteration

IterableとIterator

Iterable = Iteratorを備えた(Symbol.iteratorプロパティにIteratorを返すメソッドを実装している)オブジェクト。Iteratorを備えているのでfor-ofで処理できる。
Iterator = next()メソッドを実装したオブジェクト。nextメソッドを呼ぶと以下2つのプロパティをもったオブジェクトを返す。

  • value 現在の値
  • done 値を出し終えたかどうか

最初からIterableな挙動が備わっているもの

はじめからSymbol.iteratorプロパティにIteratorを返すメソッドが実装されているもの

  • Array
  • String
  • NodeList
  • Generator Object
  • Array, Map, Set が持つ entries(), keys(), values()の戻り値

など。
たとえば文字列で順番にとりだしたいとき以下のように書ける

const s = 'javascript';
const sIterator =  s[Symbol.iterator]();
sIterator.next();//Object {value: "j", done: false}
sIterator.next();//Object {value: "a", done: false}
sIterator.next();//Object {value: "v", done: false}
sIterator.next();//Object {value: "a", done: false}
sIterator.next();//Object {value: "s", done: false}
sIterator.next();//Object {value: "c", done: false}
sIterator.next();//Object {value: "r", done: false}
sIterator.next();//Object {value: "i", done: false}
sIterator.next();//Object {value: "p", done: false}
sIterator.next();//Object {value: "t", done: false}
sIterator.next();//Object {value: undefined, done: true}

for-ofを使ってとりだすとき

const a = ['j','a','v','a','s','c','r','i','p','t'];
const aIterator =  a[Symbol.iterator]();
for (variable of aIterator) {
  console.log(variable);
}
//j
//a
//v
//a
//s
//c
//r
//i
//p
//t

使い方はここ qiita.com

がとてもまとまってました。ありがとうございます。

Symbolについて

オブジェクトに対して、ある状況に応答するためのインターフェースを組み込む(プロトコルを定義する)ために使う。

const sym = Symbol();

で生成できる。newをつけない。
常に別々のユニークな値として生まれる。

オブジェクトのプロパティとして使うとObject.keys()などで無視される。

GlobalSymbolRegistry

グローバルスコープを越えて共有されるSymbolの領域。 iframeなどを隔てたとしても同じSymbolを共有することができる。
Symbol.for(key)メソッドを使うと keyとして渡した値を持ったSymbolがGlobalSymbolRegistryに存在しなければ、新しく生成したSymbolを生成して返す。

Generatorについて

処理を途中で抜けられる。そのときに値を取り出すことができる。 Generatorオブジェクトはnextメソッドを呼びだすと、 yieldの後に置かれている処理を評価するところまで進み、その評価結果を返す。 返ってくるオブジェクトの中身は

  • value : yieldの後の処理
  • done : すべての値を取り出し終えたかどうか

書き方

function* generatorFunc() {
  yield 1;
  yield 2;
  return 3;
}
var g = generatorFunc();
console.log(g.next()); //Object {value: 1, done: false}
console.log(g.next()); //Object {value: 2, done: false}
console.log(g.next()); //Object {value: 3, done: true}

function* と記述すると定義できる。