반복(Iteration)이란 데이터 세트 에서 일정한 순서로 데이터를 지속적으로 추출하는 과정을 말합니다.
그렇다면 반복과 순회의 차이점은 무엇입니까?
JavaScript에서 iterator는 반복을 구현하기 위해 next
메서드를 호출할 수 있는 객체입니다. 두 가지 속성을 가진 객체를 반환합니다.
value
: 반복 가능한 객체의 다음 값done
: 모든 데이터가 검색되었는지 여부를 나타냅니다. false
아직 데이터가 있음을 의미하고, true
나중에 데이터가 없음을 의미합니다.반복 가능한 객체의 반복자 팩토리 함수 Symbol.iterator
를 통해 반복자를 생성하는 데
const arr = []console.log(arr)
const arr = [1, 2, 3] const iter1 = arr[Symbol.iterator]() // 반복자 팩토리 함수 `Symbol.iterator`를 통해 반복자를 생성합니다. console.log(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 = 새 맵() mymap.set('이름', 'clz') mymap.set('나이', 21) const iter2 = mymap[Symbol.iterator]() // 반복자 팩토리 함수 `Symbol.iterator`를 통해 반복자를 생성합니다. console.log(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`를 통해 반복자를 생성합니다. console.log(iter1) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next()) console.log(iter1.next())
서로 간섭하지 않고 반복자 팩토리 함수를 여러 번 호출하여 여러 반복자를 생성할 수 있습니다. 각 반복자는 반복 가능한 객체의 일회성 순회를 나타냅니다. 서로 다른 반복자는 서로 간섭하지 않으며 반복 가능한 객체만 독립적으로 순회합니다 .
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의 구성) { console.log(i) // 1, 2, 3을 순서대로 출력 }
반복 중에 반복 가능한 객체가 수정되면 반복자가 얻은 결과도 수정됩니다.
const arr = [1, 2, 3] console.log(arr) const iter = arr[Symbol.iterator]() console.log(iter.next()) 도착[1] = 999 console.log(iter.next()) console.log(iter.next())
done: true
로 반복하면 next
호출할 때 오류가 보고됩니까, 아니면 아무것도 반환되지 않습니까?
그러나 아니요, 반복자는 완료되었지만 완료되지 않은 상태입니다. 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())
위의 예에서 iterator는 iterator 팩토리 함수 Symbol.iterator
통해 생성된다는 것을 알 수 있으므로 iterator iterator 팩토리 함수를 구현해야 하며 그런 다음 iterator가 next
메서드를 호출할 수 있으므로 다음도 수행해야 합니다. next
메서드를 구현합니다. 반복자 팩토리 함수는 실제로 this
를 직접 반환합니다.
카운터 예:
클래스 Counter { 생성자(한계) { this.count = 1 this.limit = 제한 } 다음() { if (this.count <= this.limit) { 반품 { 완료: 거짓, 값: this.count++ } } 또 다른 { return { 완료: true, 값: 정의되지 않음 } } } [Symbol.iterator]() { 이것을 돌려줘 }}
const 카운터 = 새 카운터(3) const iter = 카운터[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 (let i of counter) { console.log(i)}
for-of
루프를 사용하면 일회용이 됩니다. 이는 count
이 인스턴스의 변수이기 때문에 두 반복에서 모두 동일한 변수가 사용되기 때문입니다. 그러나 변수의 첫 번째 루프 이후에는 한계를 초과했기 때문에 for-of
루프를 사용해도 아무것도 얻을 수 없습니다. 또 결과가 나왔습니다.
count
변수를 클로저에 넣은 다음 클로저를 통해 반복자를 반환하여 생성된 각 반복자가 새 카운터에 해당하도록 할 수 있습니다.
클래스 카운터 { 생성자(한계) { this.limit = 제한 } [Symbol.iterator]() { 개수 = 1로 놔두세요 const 제한 = this.limit return { // 반복자 팩토리 함수는 next 메소드를 사용하여 객체를 반환해야 합니다. 반복은 실제로 next 메소드를 호출하여 구현되기 때문입니다. next() { if (개수 <= 제한) { 반품 { 완료: 거짓, 값: 개수++ } } 또 다른 { return { 완료: true, 값: 정의되지 않음 } } } } }}
테스트
const counter = new Counter(3)for (let i of counter) { console.log(i)}console.log('또 다른 반복:')for (let i of counter) { console.log(i)}
것은 for-of
루프를 사용하는 것과 같습니다. 반복자가 일찍 종료되면 next
메서드도 호출됩니다 return
[Symbol.iterator]() { 개수 = 1로 놔두세요 const 제한 = this.limit return { // 반복자 팩토리 함수는 next 메소드를 사용하여 객체를 반환해야 합니다. 반복은 실제로 next 메소드를 호출하여 구현되기 때문입니다. next() { if (개수 <= 제한) { 반품 { 완료: 거짓, 값: 개수++ } } 또 다른 { return { 완료: true, 값: 정의되지 않음 } } }, 반품() { console.log('반복자의 조기 종료') 반환 { 완료: 참 } } }}
테스트
const counter = new Counter(5)for (let i of counter) { if (i === 3) { 부서지다; } console.log(i)}
반복자가 닫혀 있지 않으면 중단한 부분부터 반복을 계속할 수 있습니다 . 배열 반복자는 닫을 수 없습니다.
const arr = [1, 2, 3, 4, 5]const iter = arr[Symbol.iterator]()iter.return = function () { console.log('반복자를 조기 종료') 반품 { 완료: 사실 }}for(iter의 구성) { console.log(i) if (i === 2) { 부서지다 }}for(iter의 구성) { console.log(i)}