potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

JavaScriptの反復処理(反復可能と反復子)はプロトコル

JavaScriptの反復処理はプロトコルとして実装されています。反復処理プロトコルは反復可能プロトコル(Iterable protocol)と反復子プロトコルIterator protocol)からなり、これらはオブジェクトが次表の条件を満たすことを求めます。

プロトコルはあくまでも条件であり、C++C#のようにインターフェイスやクラスの継承は求めません。

プロトコル 条件
反復可能プロトコル 反復子プロトコルを満たすオブジェクトを返す引数なしのメソッド[Symbol.iterator]()を持つ。
反復子プロトコル 次のプロパティを持つオブジェクトを返す引数なしのメソッドnext()を持つ。done:反復処理の終了を表すBoolean型の値(trueで反復終了)、value:任意の型の反復結果(donetrueなら省略可能)。

例えば、次のコードの変数o1は反復処理プロトコルを満たし、その[Symbol.iterator]メソッドの戻り値は反復子プロトコルを満たします。

const o1 = {
    [Symbol.iterator]() {
        return {
            i: 1,
            next() {return {done: this.i == 4, value: this.i++};}
        };
    }
};
console.log([...o1]); // [1, 2, 3]

反復処理は主に以下で使用されます。

  • for (const value of iterable)
  • [...iterable]

なお、反復子はジェネレータ関数function*を用いて簡単に定義できます。

const o1 = {
    [Symbol.iterator]: function* () {
        yield 1;
        yield 2;
        yield 3;
    }
};
console.log([...o1]); // [1, 2, 3]

ジェネレータ関数の簡略表記も使えます。

const o1 = {
    *[Symbol.iterator]() {
        yield 1;
        yield 2;
        yield 3;
    }
};
console.log([...o1]); // [1, 2, 3]

参考