語法
js
new Iterator()
引數
無。
返回值
一個新的 Iterator 物件。
異常
TypeError-
當
new.target是Iterator函式本身時,即當Iterator建構函式本身被構造時。
描述
Iterator 代表一個抽象類——一個為子類提供通用實用程式的類,但本身不打算被例項化。它是所有其他迭代器類的超類,用於建立實現特定迭代演算法的子類——即,所有 Iterator 的子類都必須根據 迭代器協議 實現 next() 方法。由於 Iterator 實際上不提供 next() 方法,因此直接構造 Iterator 沒有意義。
您還可以使用 Iterator.from() 從現有的可迭代物件或迭代器物件建立 Iterator 例項。
示例
繼承 Iterator
以下示例定義了一個自定義資料結構 Range,它允許迭代。為了使物件可迭代,我們可以提供一個生成器函式形式的 [Symbol.iterator]() 方法。
js
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);
}
這可行,但不如內建迭代器那樣好。有兩個問題:
- 返回的迭代器繼承自
Generator,這意味著對Generator.prototype的修改將影響返回的迭代器,這是一個抽象洩露。 - 返回的迭代器不繼承自定義原型,這使得如果我們想向迭代器新增額外方法會更加困難。
我們可以透過繼承 Iterator 來模仿內建迭代器(例如 map 迭代器)的實現。這使我們能夠定義額外的屬性,例如 [Symbol.toStringTag],同時使迭代器輔助方法在返回的迭代器上可用。
js
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 例項。
規範
| 規範 |
|---|
| ECMAScript® 2026 語言規範 # sec-iterator-constructor |
瀏覽器相容性
載入中…