↑昨年イテレータについて後日読もうと思っていたんですが、ようやくその「後日」が来ました。
イテレータ・ジェネレータ(ついでにシンボルもちょっとだけ)について覚えたことをメモ。
自分で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* と記述すると定義できる。