1. このページの目的
- ES6 の Generator を思い出したくなった時に参照するページにする。
- 自分にとってのポイントをまとめる。
2. 関連するプロトコル(インタフェース)
iterable プロトコル
for..of
に対応する。- iterator プロトコルに準拠するオブジェクトを返す [Symbol.iterator] プロパティ(メソッド)を実装する。
String
,Array
,TypeArray
,Map
,Set
, は iterable である。つまり、[Symbol.iterator] プロパティをメソッドとして実行すると、iterator オブジェクトが返ってくる。つまりこれらは「ビルトインの反復可能オブジェクト」である。- それに対して、[Symbol.iterator] を、
function* () { ... }
を使って自分で定義するのが「ユーザー定義の反復可能オブジェクト」である。
JavaScriptコード
let o = "Hi"[Symbol.iterator](); // StringIterator {}
o.next(); // { value: "H", done: false }
o.next(); // { value: "i", done: false }
o.next(); // { value: undefined, done: true }
o.next(); // { value: undefined, done: true }
iterator プロトコル
next()
メソッドを実装するdone
(boolean) もしくはvalue
が返る。
3. ジェネレーター関数(function* () { ... }
で定義する)
Generator
オブジェクトを返す関数を定義することができる。この関数のことを「ジェネレーター関数」と呼ぶ。Generator
オブジェクトは、iterable
プロトコルとiterator
プロトコルの両方に準拠している。- 自分で return を書くわけではない。
JavaScriptコード
function* gen() {
yield 1;
yield 2;
yield 3;
}
for (let n of gen()) {
console.log(n);
}
4. Generator オブジェクト
Generator
オブジェクトは、iterable
プロトコル /iterator
プロトコルの両方に対応している。- そのため、[Symbol.iterator] プロパティも実装しているし、
next()
メソッドも実装している。 - [Symbol.iterator] を実行すると
iterator
オブジェクトが返るわけだが、この返ってきたオブジェクトは元のオブジェクトと同じ状態を参照しているようだ。なぜ、こんなふうになっているかまでは、まだ理解していない。
JavaScriptコード
function* gen() {
yield 1;
yield 2;
yield 3;
}
let g = gen();
console.log(g.next()); // { value: 1, done: false }
let h = g[Symbol.iterator](); // g から iterator オブジェクトを取り出す
console.log(h.next()); // { value: 2, done: false } ← 同じオブジェクトを参照している
Methods
Generator.prototype.next()
Generator.prototype.return()
Generator.prototype.throw()
5. メモ
- Symbol を使った [Symbol.iterator] といったプロパティは、「@@iterator」とも表現できるようだ。
6. 参考
- ECMAScript 2015 Language Specification – ECMA-262 6th Edition
- Generator - JavaScript | MDN
- 反復処理プロトコル - JavaScript | MDN
- function* - JavaScript | MDN
- for...of - JavaScript | MDN
7. 履歴
日付 | 内容 |
---|---|
作成 | 2019-05-10 |