Iterator() コンストラクター
Limited availability
This feature is not Baseline because it does not work in some of the most widely-used browsers.
Iterator()
コンストラクターは、イテレーターを作成する他のクラスのスーパークラスとして意図通りに使用されることを目的としています。これ自体で構築された場合、エラーが発生します。
構文
引数
なし。
返値
新しい Iterator
オブジェクトです。
例外
TypeError
-
new.target
がIterator
関数事態に呼び出された場合、つまり、Iterator
コンストラクターそれ自身が構築された場合。
解説
Iterator
は抽象クラスを表します。抽象クラスとは、サブクラスに対して指定された共通のユーティリティを提供するクラスですが、それ自体がインスタンス化されることを意図していません。これは、他にもイテレータークラスのスーパークラスであり、特定の反復処理アルゴリズムを実装するサブクラスを作成するために使用されます。つまり、 Iterator
のすべてのサブクラスは、イテレータープロトコルで要求されるように、 next()
メソッドを実装する必要があります。 Iterator
は実際には next()
メソッドを提供していないため、 Iterator
を直接構築することは意味がありません。
また、 Iterator.from()
を使用して、既存の反復可能オブジェクトまたはイテレーターオブジェクトから Iterator
のインスタンスを作成することもできます。
例
Iterator のサブクラス化
次の例では、反復処理が可能なカスタムデータ構造である Range
を定義しています。オブジェクトを反復処理可能にするには、ジェネレーター関数という形で [Symbol.iterator]()
メソッドを提供します。
class Range {
#start;
#end;
#step;
constructor(start, end, step = 1) {
this.#start = start;
this.#end = end;
this.#step = step;
}
*[Symbol.iterator]() {
for (let value = this.#start; value <= this.#end; value += this.#step) {
yield value;
}
}
}
const range = new Range(1, 5);
for (const num of range) {
console.log(num);
}
これはうまく動作しますが、組み込みのイテレーターの作業方法ほど優れてはいません。 2 つの問題があります。
- 返されたイテレーターは
Generator
を継承しており、これはGenerator.prototype
への変更が返されたイテレーターに影響することを意味しており、抽象化の漏れです。 - 返されたイテレーターはカスタムプロトタイプを継承しないため、イテレーターに追加のメソッドを意図通りに追加するのが難しくなります。
Iterator
をサブクラス化することで、組み込みのイテレーター(例えば、マップのイテレーター)の実装を模倣することができます。これにより、 [Symbol.toStringTag]
などの追加のプロパティを定義することができ、返値のイテレーターにおいてイテレーターのヘルパーメソッドを利用できるようになります。
class Range {
#start;
#end;
#step;
constructor(start, end, step = 1) {
this.#start = start;
this.#end = end;
this.#step = step;
}
static #RangeIterator = class extends Iterator {
#cur;
#s;
#e;
constructor(range) {
super();
this.#cur = range.#start;
this.#s = range.#step;
this.#e = range.#end;
}
static {
Object.defineProperty(this.prototype, Symbol.toStringTag, {
value: "Range Iterator",
configurable: true,
enumerable: false,
writable: false,
});
// Avoid #RangeIterator from being accessible outside
delete this.prototype.constructor;
}
next() {
if (this.#cur > this.#e) {
return { value: undefined, done: true };
}
const res = { value: this.#cur, done: false };
this.#cur += this.#s;
return res;
}
};
[Symbol.iterator]() {
return new Range.#RangeIterator(this);
}
}
const range = new Range(1, 5);
for (const num of range) {
console.log(num);
}
サブクラス化パターンは、多数の独自のイテレーターを作成したい場合に便利です。 Iterator
を継承していない反復可能オブジェクトやイテレーターオブジェクトがあり、そのオブジェクトにイテレーターのヘルパーメソッドを呼び出したいだけの場合、 Iterator.from()
を使用して、一時的に Iterator
インスタンスを作成することができます。
仕様書
Specification |
---|
Iterator Helpers # sec-iterator-constructor |
ブラウザーの互換性
BCD tables only load in the browser