Iterable와 Iterator

Dorr·2021년 8월 10일
0
post-custom-banner

리스트 순회

ES5에서의 리스트 순회

// 리스트 순회
const list = [1, 2, 3];

for (var i = 0; i < list.length; i++) {
  console.log(list[i]);
}

// 유사배열 순회
const str = "abc";

for (var i = 0; i < str.length; i++) {
  console.log(str[i]);
}

프로퍼티에 의존하여 어떻게 순회할 지 명령적으로 표현됨

ES6+에서의 리스트 순회

// 리스트 순회
const list = [1, 2, 3];

for (const num of list) {
  console.log(num);
}

// 유사배열 순회
const str = "abc";

for (const char of str) {
  console.log(char);
}

보다 선언적이고 간결해짐 -> 문법을 보기 좋게 다듬은 것이 전부 일까?

ES6+에서는 순회를 어떻게 추상화하였는가?

for ... of 문의 순회 방식은 무엇일까?

const arr = [1, 2, 3];
const set = new Set([1, 2, 3]);
const map = new Map([
  ["a", 1],
  ["b", 2],
  ["c", 3],
]);

for (const el of arr) console.log(el); // 1, 2, 3
for (const el of set) console.log(el); // 1, 2, 3
for (const el of map) console.log(el); // ["a", 1], ["b", 2], ["c", 3]

ES6 이전의 순회 방식은 index를 key로 두고 index의 값을 1씩 증가하면서 순회한다.
그렇다면 ES6+ 에서도 동일한 방식으로 순회를 할까?

답은 '아니오'이다.

set[0]; //undefined
set[1]; //undefined
set[2]; //undefined

map[0]; // undefined
map[1]; // undefined
map[2]; // undefined

만약 index을 키로 두고 사용하는 방식이라면 위의 예시에서 undefined가 출력되지 않았을 것이다. 그렇다면 for...of의 순회 방법은 무엇일까?

iterable / iterator

iterable

  • iterator을 리턴하는 [Symbol.iterator] 메서드를 가진 객체

iterator

{value: , done: } 객체를 리턴하는 next() 메서드를 가진 객체

{value, done} 객체

  • value : 현재 값이 담겨있다.
  • done : 불리언 값을 가지며 반복의 종료를 결정한다.

직접 만들어보며 이해해보자!

직접 이터러블 객체를 만들어보면서 이터러블 개념을 이해해보자

let iterableObj = {
  from: 1,
  to: 5,
};

//for (const num of iterableObj)가 작동하여 num = 1,2,3,4,5로 순회하게 해보자.
  1. iterable은 iterator 객체를 리턴하는 [Symbol.iterator] 메서드를 가져와야한다.
iterableObj[Symbol.iterator] = function () {
  const iterator = {};

  return iterator;
};
  1. iterator은 {value, done}객체를 리턴하는 next() 메소드를 가져야한다.
iterableObj[Symbol.iterator] = function () {
  const iterator = {
    next() {
      return { value: null, done: null };
    },
  };

  return iterator;
};
  1. value는 현재 값을 가지고, done은 종료 조건을 갖늗다.
iterableObj[Symbol.iterator] = function () {
  const iterator = {
    current: this.from,
    last: this.to,

    next() {
      if (this.current <= this.last) {
        return {
          value: this.current++,
          done: false,
        };
      } else {
        return { done: true };
      }
    },
  };

  return iterator;
};
  1. 완성 코드
let iterableObj = {
  from: 1,
  to: 5,
};

iterableObj[Symbol.iterator] = function () {
  const iterator = {
    current: this.from,
    last: this.to,

    next() {
      if (this.current <= this.last) {
        return {
          value: this.current++,
          done: false,
        };
      } else {
        return { done: true };
      }
    },
  };

  return iterator;
};

for (const num of iterableObj) {
  console.log(num);
}
// 1 2 3 4 5

for...of루프는 [Symbol.iterator] 메서드를 통해 iterator객체를 생성하고 iterator는 done이 true가 될 떄까지 next()를 호출하여 순회시킨다.

전개 연산자

iterable 객체는 전개 연산자(...)를 사용할 수 있다.

post-custom-banner

0개의 댓글