ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [함수형 프로그래밍] 이터레이터와 이터러블이란?
    JavaScript 2022. 1. 31. 17:57

    new 키워드를 통해 Map객체를 만들면 안에 들어 있는 파라미터는 iterable인 값을 넣어주도록 명시하고 있습니다.

    여기서 iterable은 어떤것을 의미할까요?

    또한 기존의 es5에서는 for(let i = 0; i<arr.length; i++){} 와 같은 형태로 어떻게 동작을 하는지 명령적으로 작성해주어야 했습니다.

    하지만 es6에서는 아래와 같은 형태로 보다 선언적으로 순회를 할 수 있습니다.

    for (const a of map) {
      console.log(a);
    }

    Map객체 뿐만 아니라 배열과 Set객체 또한 for of문을 통해 순회할 수 있는데요, 어떻게 동작할까요?

     

     

    이터레이터와 이터러블 

    Map객체는 Symbol.iterator라는 키를 가지고 있습니다.

    이를 동적할당을 통해 Map객체의 Symbol.iterator의 값이 어떤것인지 알아보겠습니다.

    console.log(map[Symbol.iterator]); // [Function: entries]

     

     

    map객체의 Symbol.iterator라는 키는 entries라는 함수를 값으로 가지고 있는것을 알 수 있습니다.

    그럼 여기서 이터러블과 이터레이터의 정의를 먼저 살펴보고 가겠습니다.

     

    이터레이터란 {value, done}객체를 반환하는 next()를 가진 값을 말합니다.

    이터러블이란 이터레이터를 반환하는 [Symbol.iterator]()를 가진 값을 말합니다.

    아직까지는 잘 와닿지 않을 수 있습니다.

    결론적으로 Map객체는 이터러블하면서 동시에 이터레이터라 할수 있는데요, 아래의 코드를 보면서 하나씩 이해해 보겠습니다.

     

     

    위에서 우리는 map객체가 Symbol.iterator라는 키를 가지고 있는것을 보았습니다.

    또한 결론적으로 이터러블이라는것도 알고 있는데요, 이것이 어떤 의미를 가지는지 보겠습니다.

    const iter = map[Symbol.iterator]();
    // map객체는 Symbol.iterator라는 키를 가지고 있는데 그 값은 함수이며, 
    // 함수를 실행했을 때에는 이터레이터를 반환합니다.
    // 밑에서 이터레이터를 반환하는지 더 알아보겠습니다.
    
    console.log(iter); //[Map Entries] { [ 'a', 1 ], [ 'b', 2 ] }
    
    // 다시 알아보는 이터레이터의 정의
    // 이터레이터는 {value, done}을 키로 가지는 객체로 구성되어있으며, next메서드를 가지고 있습니다. 
    
    console.log(iter.next()) // { value: [ 'a', 1 ], done: false }
    
    //iter.next()를 한다면 value와 done을 키로 가지는 객체를 반환합니다.
    // 따라서 우리는 iter가 이터레이터라는것을 알 수 있습니다.
    // 또한 map객체의 Symbol.iteraotr 키의 값인 entries 함수를 실행한다면 이터레이터를 반환하는것을 알 수 있습니다.

     

    for of 문 살펴보기

    그렇다면 이제 for of 문이 어떻게 동작하는지 살펴보겠습니다.

    const map = new Map([
      ["a", 1],
      ["b", 2],
      ["c", 3],
    ]);
    
    const iter = map[Symbol.iterator](); //이터레이터를 반환합니다.
    
    console.log(iter.next()); // { value: [ 'a', 1 ], done: false }
    console.log(iter.next()); // { value: [ 'b', 2 ], done: false }
    console.log(iter.next()); // { value: [ 'c', 3 ], done: false }
    console.log(iter.next()); // { value: undefined, done: true }

     

    뭔가 for문과 비슷하지 않나요? 다시 한번 해 보겠습니다.

    const map = new Map([
      ["a", 1],
      ["b", 2],
      ["c", 3],
    ]);
    
    const iter = map[Symbol.iterator]();
    iter.next();
    for (const a of iter) {
      console.log(a); // [ 'b', 2 ], [ 'c', 3 ]이 차례로 출력
    }

    이제 우리는 map, set, array가 각기 다른 모습으로 구현이 되어있지만 내부적으로 이터레이터와 이터러블을 가지고 있다는 것을 알 수 있습니다. 또한 이를 이용해 for of 문을 사용할 수 있습니다.

     

    keys, values, entries 메서드

    우리는 map에 keys, values, entries메서드가 있다는것을 알고 있고 이 또한 for of 문으로 순회가능하다는 것을 알고 있습니다.

    그렇다면 한번 로그를 확인해 볼까요?

    console.log(map.keys()); // [Map Iterator] { 'a', 'b', 'c' }

     이렇게 이터레이터를 반환한다는것을 알 수 있습니다.

    또 다른것을 해보도록 하겠습니다.

    const iter = map.keys();
    console.log(iter); // [Map Iterator] { 'a', 'b', 'c' }
    console.log(iter[Symbol.iterator]()); // [Map Iterator] { 'a', 'b', 'c' }

    둘다 이터레이터를 반환하는것을 알 수 있는데요, keys 메서드를 실행한 결과는 Symbol.iterator라는 키를 가지고 있고, 그 키를 실행시킨 결과는 이터레이터를 반환한다는것을 알 수 있습니다. 즉, 이터레이터이면서 이터러블하기 때문에 keys 메서드를 통해 순회를 할 수 있게 됩니다.

    댓글

Designed by Tistory.