Javascript의 Iterator(반복자)는 next 메서드를 가지고 있는 객체이고 이 메서드는 원소들을 탐색하며, next 메서드의 호출시마다 새로운 객체를 반환한다. 반복자는 두 개의 속성(value, done)을 반환하는 next() 메소드 사용하여 객체의 Iterator protocoal을 구현한다.
기본적인 개념을 알았으니 한번 간단한 예시를 들어 사용해보자
밑의 코드는 아래 iterable Array의 원소값을 차례로 나열해줄 수 있게 iterator를 사용한 것이다.
const iterable = [1, 2, 3]
const iterator = iterable[Symbol.iterator]();
while (true) {
const iteratorResult = iterator.next()
if (iteratorResult.done) break;
console.log(iteratorResult.value)
}
// 결과 값
/*
1
2
3
*/
iterator의 탐색이 완료되면 done의 값은 true를 반환하므로 무한루프가 종료된다.
좀 더 심화과정으로 iterator를 이용하여 피보나치 수열을 생성하는 코드를 작성해보자
const fibonacci = {
[Symbol.iterator]() {
let n1 = 0, n2 = 1, value;
return {
next() {
value = n1;
n1 = n2;
n2 = value + n2;
if (value > 100) {
return {done: true};
} else {
return {value};
}
}
};
}
};
for (const n of fibonacci) {
console.log(n);
}
// 실행결과
/*
0
1
1
2
3
5
8
13
21
34
55
89
*/
계산하는 수가 100이상이 되면 return {done: true} 를 통해 iterator 종료된다.
Genarator(생성자)는 Itearble하면서 Iterator인 객체의 특별한 종류이다. 이 객체는 일시정지와 재시작 기능을 여러 반환 포인트들을 통해 사용이 가능하다. 이런 반환 포인트들은 yield 라는 키워드를 통해 구현이 가능하며 next 를 호출시마다 다음 yield 값이 반환된다. Iterator과 마찬가지로 value와 done이 호출되며 Generator의 yield값이 value값으로 반환이 된다.
이제 간단한 예시를 들어보자
function* generatorFunction() {
let i = 0;
while (true) {
yield i++
}
}
const generator = generatorFunction();
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
//실행결과
/*
{ value : 0, done: false }
{ value : 1, done: false }
{ value : 2, done: false }
{ value : undefined, done: true }
*/
이처럼 일반함수였으면 while문의 break를 안넣어주었기 때문에 무한루프가 되는 함수 이었지만 generator를 통해 생성된 함수이기 때문에 호출할때마다 i의 값이 1씩 늘어나는 것을 알 수 있다.
그런데 이런 generator를 왜 사용하는 것일까?
이유는 일반 반복문보다 generator를 활용한 코드가 좀더 빠르게 작용하기 때문이다.
밑의 예시 코드를 봐보자
function newArr(n) {
let i = 1;
const res = [];
while (i < n) res.push(i++);
return res;
}
function* newArrGen(n) {
let i = 1;
while (i < n) yield i++;
}
function fiveArr(iter) {
const res = [];
for (const item of iter) {
if (item % 5 == 0) res.push(item);
else if (res.length == 2) break;
}
return res;
}
console.log(fiveArr(newArr(100)));
console.log(fiveArr(newArrGen(100)));
이 함수는 newArr이 즉시 배열을 만들어내고 1~99까지 만들어진 배열을 리턴해서 fiveArr함수를 수행하게 된다. 즉 fiveArr([1,2,3,...97,98,99])가 된다는 것이다.
이 함수는 newArrGen이 interator 만 만들어 내고 fiveArr 함수에서 필요할 때 이터레이터에서 평가된 값을 사용한다.
위의 두 함수의 시간은 배열의 크기가 크면 클 수록 비약적으로 newArrGen 함수가 짧아지며 이는 즉시 평가를 하는 일반 함수와 달리 지연 평가를 하는 generator가 확실히 빠르게 동작하는 것을 볼 수 있다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Iterators_and_Generators
https://bbaktaeho-95.tistory.com/80