ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Section 10. 자바스크립트 이터러블
    자바스크립트 2023. 4. 7. 12:01

    I. 이터러블 프로토콜 iterable protocol

    • 반복, 순회 기능을 사용하는 주체간의 통일된 규격이다.
    • 공통 기능들 : for ... of, 스프레드 문법, 배열 디스트럭쳐링

     

    이터러블 iterable - 이터러블 프로토콜을 준수하는 객체

    • 배열, 문자열, Set, Map, arguments 등 ...
    • 키 Symbol.iterator (well-known 심볼)의 값으로 이터레이터를 반환하는 메서드를 가진다.

    *Symbol.iterator같이 잘 알려져서 많은 것들의 식별자로 사용되는 것을 well-known 심볼이라 한다.

     

    배열 하나를 출력해보자.

    []

    그리고 콘솔에서 그걸 펼쳐보면 다음과 같다.

    프로토타입 밑에 Symbol.iterator를 키로하는 어떤 함수가 들어있는 것을 볼 수 있다.

    이 프로퍼티가 이터레이터의 핵심이다.

    console.log(
      [][Symbol.iterator],
      ''[Symbol.iterator],
      new Set()[Symbol.iterator],
      new Map()[Symbol.iterator]
    );

    배열, 문자열, Set, Map에 대한 Sysmbol.iterator의 값을 출력해봤다. 출력문은 다음과 같다.

    공통적으로 어떤 함수들이 출력 되는 것을 볼 수 있다.

    이런 함수들은 이터러블이 아닌 함수에는 존재하지 않는다.

    // 다른 타입의 인스턴스에는 없음
    console.log(
      (1)[Symbol.iterator],
      (true)[Symbol.iterator],
      { x: 1 }[Symbol.iterator]
    ); //undefined undefined undefined

     

    이 함수들을 실행 괄호 ()를 붙여서 실행해보면

    console.log(
      [][Symbol.iterator](), //Array Iterator {}
      ''[Symbol.iterator](), //StringIterator {}
      new Set()[Symbol.iterator](), //SetIterator {}
      new Map()[Symbol.iterator]() //MapIterator {}
    );

    각각 해당하는 자료형의 이터레이터를 반환하는 것을 알 수 있다.

     

    II. 이터레이터 iterator

    next 메서드를 통해 이터러블을 순회하며 값을 반환한다.

    const arr = [1, 'A', true, null, {x: 1, y: 2 }];
    const arrIterator = arr[Symbol.iterator]();
    
    console.log(arrIterator);

    arr의 심볼 이터레이터에 접근해서 arrIterator를 뽑아냈다.

    그리고 그것을 출력해보면 next()라는 함수를 가지고 있는 것을 볼 수 있다.

    arr[Symbol.iterator]()를 통해서 반환된 Array Iterator 객체는 next라는 함수(기능)를 가지고 있는 것이다.

    이 기능을 이용하면 arr의 요소들을 차례대로 뽑아낼 수 있다.

    arrIterator.next(); //{value: 1, done: false}
    arrIterator.next(); //{value: 'A', done: false}
    arrIterator.next(); //{value: true, done: false}
    arrIterator.next(); //{value: null, done: false}
    arrIterator.next(); //{value: {…}, done: false}
    arrIterator.next(); //{value: undefined, done: true}

     

    이터레이터 프로토콜 iterator protocol

    next 메서드의 반환 객체 내 요소는 다음과 같다

    • value - 해당 차례에 반환할 값
    • done - 순회 종료 여부 (마지막 값 반환 다음 차례부터)

    III. 이터러블 만들어보기

    주사위를 열 번 굴리는 이터러블

    const diceTenTimes = {
      // ⭐️ 아래의 메서드를 갖는 것이 이터러블 프로토콜
      [Symbol.iterator] () {
        let count = 0;
        let maxCount = 10;
        
        // ⭐️ 이터레이터(next 메서드를 가진 객체)을 반환
        return {
          next () {
            return {
              value: Math.ceil(Math.random() * 6),
              done: count++ >= maxCount
            }
          }
        }
      }
    }

    diceTenTimes라는 객체를 하나 만들었다.

    이 객체에 Symbol.iterator를 키로 하려면 [ ]를 써줘야 한다. 거기에 실행 괄호가 붙어서  심볼 이터레이터라는 메서드가 실행 된다. 

    이 메서드는 이터레이터 객체를 반환한다. 그 객체에는 next라는 함수가 있고 그 함수가 반환하는 것은 

    value: Math.ceil(Math.random() * 6),

    done: count++ >= maxCount

    이것이 되는 것이다. 

     

    실행을 해보면 다음과 같다

    const diceIterator = diceTenTimes[Symbol.iterator]();
    
    for (let i = 0; i < 12; i++) {
      console.log(
        diceIterator.next()
      );
    }

    여기서 next의 done 프로퍼티가 true를 반환 했는데도 계속 출력된 이유는 for문의 종료 조건때문이다. 

     

    for ... of 문도 사용이 가능하다.

    // 💡 for ... of 문 사용 가능
    for (const num of diceTenTimes) {
      console.log(num);
    }

    for 문과는 다르게 딱 10번 출력된 것을 볼 수 있다. 

    스프레드 문법도 사용 가능하다.

    const diceResults = [...diceTenTimes];
    
    console.log(diceResults); //[5, 1, 5, 4, 3, 3, 4, 1, 1, 2]

     

    *이 예시는 제너레이터로 보다 간편하게 구현이 가능하다.

Designed by Tistory.