iterator 와 for-of

2020. 4. 10. 12:53웹/Javascript(ES6+)

iterator

  • 반복 처리가 가능한 객체

  • 시퀀스를 정의하고  종료시의 반환값을 잠재적으로 정의하는 객체

  • 반복자는 두 개의 속성(value, done)을 반환하는 next() 메소드 사용하여 객체의 iterator protocol 을 구현

  • 반환되는 value 속성은 현재 iterator 가 가리키는 곳의 값을 가리키며, done 속성은 iterator 가 끝까지 도달했는지를 구분해주는 true/flase 값을 가짐

  • Array, String, Map, Set, DOM이 iterable, 이러한 요소를 탐색할 수 있게 하는 객체가 iterator

 

예제)

const furitArr = ['사과', '배', '오렌지'];
const iterator = furitArr[Symbol.iterator]();

console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

-- 출력 결과 --
{value: "사과", done: false]
{value: "배", done: false]
{value: "오렌지", done: false]
{value: undefined, done: true]

 

예제) Arry.prototype[Symbol.iterator]()

 

예제) String.prototype[Symbol.iterator]()

 

 

※ iterator protocol

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol

 

 

 

for-of 문

  • 반복가능한 객체 (Array, Map, Set, String, TypedArray, arguments 객체 등을 포함)에 대해서 반복

  • 각 개별 속성값에 대해 실행되는 문이 있는 사용자 정의 반복 후크를 호출하는 루프를 생성

 

예제)

const fruitArr= ['사과', '배', '오렌지'];

for(const element of fruitArr){
    console.log(element);
}

-- 출력 결과 --
사과
배
오렌지

 

 

 

iterator 와 for-of 활용

예제) 피보나치 수열

const fibo = {
    maxStep: 20,
    [Symbol.iterator]() {
        let previos =0,
            current = 1,
            step = 0,
            maxStep = this.maxStep;
        
        return {
            next() {
                [previous, current] = [current, previous + current];
                return {
                    done: step++ >= maxStep,
                    value: current
                };
            }
        };
    }
};


for(const el of fibo) {
    console.log(el);
}

-- 출력 결과 --
1
2
3
5
...
6765
10946
  • Symbol.iterator 속성으로 하는 함수를 정의, next() 함수를 속성으로 가지는 객체를 반환

  • next() 함수는 으로 done, value 속성을 가짐

  • for-of 문을 통해 done 이 true 가 될때 까지 루프

 

 

예제) funtion*과 yield 키워드 사용

const fibo = {
    maxStep: 20,
    *[Symbol.iterator]() {
        let previous =0,
            current = 1,
            step = 0,
            maxStep = this.maxStep;
        
        while(step++ < maxStep) {
            [previous, current] = [current, previous + current];
            yield current;
        }
    }
};


for(const el of fibo) {
    console.log(el);
}


-- 출력 결과 --
1
2
3
5
...
6765
10946
  • generator 함수는 전체 함수가 종료되면 iterator도 종료, yield current 를 통해 값이 전달됨

  • yield current 가 호출되면 generator 함수가 잠시 멈추었다가 다음 for-of 루프를 돌때 이어서 실행

 

 

※ generator 함수

  • iterator 규격을 간단하게 처리하기 위한 generator 기능이 표준으로 정의되어 있음

  • function* 은 generator 함수이며 iterator를 반환하는 함수

  • yield 는 return과 유사, return은 함수를 끝내지만 yield 는 함수를 잠시 멈추었다가 다음에 호출되었을 때 다시 그 이후 부터 시작

 

 

예제) iterator 객체 생성

const fibo = function* (maxStep) {
    let previous =0,
        current = 1,
        step = 0;
        
    while(step++ < maxStep) {
        [previous, current] = [current, previous + current];
        yield current;
    }
};


for(const el of fibo(20)) {
    console.log(el);
}


-- 출력 결과 --
1
2
3
5
...
6765
10946
  • generator 함수를 변수에 선언하여 사용하더라도 직접 iterator 처럼 사용 가능

 

 

예제) iterator 객체를 통한 비동기 요청 흐름제어 활용

function getDOM() {
    const xhr = new XMLHttpRequest();
    xhr.open("/fetchDOM");
    xhr.onload = function() {
        xhrRequests.next(xhr.responseText);
    }
    xhr.send();
}


function getData() {
    const xhr = new XHMLHttpReqeust();
    xhr.open("/fetchData");
    xhr.onload = function() {
        xhrRequests.next(xhr.responseText);
    }
    xhr.send();
}


function manipulateDOM(dom, data) {
    // Fix DOM
}


const xhrRequests = function* () {
    let dom, data;
    dom = yield getDOM();
    data = yield getData();
    yield manipulateDOM(dom, data);
}
  • getDOM, getData, manipulateDOM 을 순서대로 호출하고자 할때 흐름 제어 

  • xhrRequests 변수는 iterator 객체로 전체 흐름을 제어, 각 함수가 실제 처리하는 역할 담당

  • xhrRequests 함수 내에서 각 순서 보장이 필요한 XHMLHttpRequest 들을 호출하고, 각 함수에서는 비동기 요청이 완료되면 onload 이벤트 핸들러를 통해 다음단계 next() 함수 호출

 

 

 

 

 

 

 

 

출처

속깊은 JavaScript(양성익)

https://jeong-pro.tistory.com/121

' > Javascript(ES6+)' 카테고리의 다른 글

비동기 처리 - async & aswait  (0) 2020.06.17
비동기 처리 - Promise  (0) 2020.06.16
Rest, Spread 연산자  (0) 2020.04.09
Destructuring(구조 분해 할당)  (0) 2020.04.08
템플릿 리터럴 문자열 표현식  (0) 2020.04.08