
反復とは、データセットから特定の順序でデータを継続的に抽出するプロセスを指します。
それでは、反復と走査の違いは何でしょうか?
では、イテレータは、反復を実装するためにnextメソッドを呼び出すことができるオブジェクトです。 2 つのプロパティを持つオブジェクトを返します。
value : 反復可能オブジェクトの次の値done : すべてのデータが取得されたかどうかを示します。 falseまだデータが存在することを意味し、 trueその後データが存在しないことを意味します。、反復可能オブジェクト内のイテレータ ファクトリ関数Symbol.iteratorを通じてイテレータを生成するためにのみ
const arr = []console.log(arr)

const arr = [1, 2, 3]
const iter1 = arr[Symbol.iterator]() // イテレータ ファクトリ関数 `Symbol.iterator` を通じてイテレータを生成します。
コンソールログ(iter1)
console.log(iter1.next())
console.log(iter1.next())
console.log(iter1.next())
console.log(iter1.next())
console.log('%c%s', 'color:red;font-size:24px;', '================')
const mymap = new Map()
mymap.set('名前', 'clz')
mymap.set('年齢', 21)
const iter2 = mymap[Symbol.iterator]() // イテレータ ファクトリ関数 `Symbol.iterator` を通じてイテレータを生成します。
コンソール.ログ(iter2)
console.log(iter2.next())
console.log(iter2.next())
console.log(iter2.next())
最後の値を取得した後、つまり、反復子の次のvalueがundefinedなったときに、反復子が完了したことがわかります。
ただし、上記のステートメントはあまり正確ではありません。イテレータの次のvalueがundefinedの場合、このステートメントは完了しません。また、実際に値が存在しないのか、それとも反復可能オブジェクトにundefined値が存在するのかを判断する必要もあります。反復可能オブジェクト内にundefined値がある場合、この時点では完了しません。
const arr = [1、2、3、未定義] const iter1 = arr[Symbol.iterator]() // イテレータ ファクトリ関数 `Symbol.iterator` を通じてイテレータを生成します。 コンソールログ(iter1) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next())

互いに干渉することなくイテレータ ファクトリ関数を複数回呼び出して、複数のイテレータを生成できます。各イテレータは、反復可能なオブジェクトの 1 回限りの順序付けられた走査を表します。異なる反復子は互いに干渉せず、反復可能なオブジェクトのみを独立して走査します。
const arr = [1, 2, 3]
const iter1 = arr[Symbol.iterator]() // イテレータ ファクトリ関数 `Symbol.iterator` を通じてイテレータを生成します。
const iter2 = arr[Symbol.iterator]()
console.log('Iterator1:', iter1.next())
console.log('Iterator2:', iter2.next())
console.log('Iterator1:', iter1.next())
console.log('Iterator2:', iter2.next())
const arr = [1, 2, 3]
const iter = arr[Symbol.iterator]()
for (iter の const i) {
console.log(i) // 1、2、3を順番に出力します
反復子は
反復中に反復可能オブジェクトが変更されると、反復子によって得られる結果も変更されます。
const arr = [1, 2, 3] コンソール.ログ(arr) const iter = arr[Symbol.iterator]() console.log(iter.next()) arr[1] = 999 console.log(iter.next()) console.log(iter.next())

done: trueを繰り返すと、 next呼び出すときにエラーが報告されますか、それとも何も返されませんか?
ただし、いいえ、イテレータは完了しましたが、完了していない状態になります。done done: true完了したが、今後もnextを呼び出すことができることを意味します。ただし、結果は常に{ value: undefined, done: true }になります。 。だからこそ、 「やっているようでやっていない」と言われているのです。
const arr = [1, 2, 3] const iter = arr[Symbol.iterator]() console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next())

上記の例から、反復子は反復子ファクトリー関数Symbol.iteratorを通じて生成されることがわかります。そのため、反復子反復子ファクトリー関数を実装する必要があります。その後、反復子はnextことも行う必要があります。 nextメソッドを実装します。イテレータ ファクトリ関数に関しては、実際にはインスタンスthis直接返します。
カウンタの例:
class Counter {
コンストラクター(制限) {
this.count = 1
this.limit = 制限 }
次() {
if (this.count <= this.limit) {
戻る {
完了: false、
値: this.count++
}
} それ以外 {
return { 完了: true、値: 未定義 }
}
}
[Symbol.iterator]() {
これを返す
}} const カウンタ = 新しいカウンタ(3) const iter = counter[Symbol.iterator]() console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next()) console.log(iter.next())

一見すると問題はありませんが、 for-of使ってトラバースしてみると問題が見つかります。
const counter = new Counter(3)for (カウンターを i にします) {
console.log(i)}console.log('別の反復:')for (カウンターの i を許可) {
コンソール.ログ(i)}
for-ofループを使用すると、ループが使い捨て可能になります。これは、 countこのインスタンスの変数であるため、両方の反復で同じ変数が使用されるためです。ただし、変数の最初のループの後、制限を超えているため、 for-ofループを使用しても何も取得されません。結果はまたそうでした。
count変数をクロージャに配置し、クロージャを介してイテレータを返すと、作成された各イテレータが新しいカウンタに対応するようになります。
クラス カウンタ {
コンストラクター(制限) {
this.limit = 制限 }
[Symbol.iterator]() {
カウント = 1 にします
const 制限 = this.limit return {
// 反復は実際には next メソッド next() を呼び出すことによって実装されるため、イテレータ ファクトリ関数は next メソッドを持つオブジェクトを返す必要があります。 {
if (カウント <= 制限) {
戻る {
完了: false、
値: count++
}
} それ以外 {
return { 完了: true、値: 未定義 }
}
}
}
}}テスト
const counter = new Counter(3)for (カウンターを i にします) {
console.log(i)}console.log('別の反復:')for (カウンターの i を許可) {
コンソール.ログ(i)}
return for-ofループを使用するのと同じです。イテレータが早期に終了すると、 nextメソッドも呼び出されます。
[Symbol.iterator]() {
カウント = 1 にします
const 制限 = this.limit return {
// 反復は実際には next メソッド next() を呼び出すことによって実装されるため、イテレータ ファクトリ関数は next メソッドを持つオブジェクトを返す必要があります。 {
if (カウント <= 制限) {
戻る {
完了: false、
値: count++
}
} それ以外 {
return { 完了: true、値: 未定義 }
}
}、
戻る() {
console.log('反復子の早期終了')
戻り値 { 完了: true }
}
}}テスト
const counter = new Counter(5)for (カウンターを i にします) {
if (i === 3) {
壊す;
}
コンソール.ログ(i)}
イテレータが閉じていない場合は、中断したところから繰り返しを続行できます。配列イテレータを閉じることはできません。
const arr = [1, 2, 3, 4, 5]const iter = arr[Symbol.iterator]()iter.return = function () {
console.log('反復子を早期に終了します')
戻る {
完了: true
}}for (iter の const i) {
コンソール.ログ(i)
if (i === 2) {
壊す
}}for (iter の const i) {
コンソール.ログ(i)}