JavaScript - 이터레이터(iterator)와 for/of 문

BigbrotherShin·2020년 3월 12일
2

JavaScript

목록 보기
15/17
post-thumbnail

모던 자바스크립트 입문(아소 히로시, 길벗, 2018)을 공부하고 정리한 내용입니다.

이터레이터

이터레이션(iteration)

이터레이션은 반복 처리라는 뜻으로 데이터 안의 요소를 연속적으로 꺼내는 행위를 말합니다.
예를 들어 배열의 forEach 메서드는 배열의 요소를 순차적으로 검색하여 그 값을 함수의 인수로 넘기기를 반복합니다.

let a = [1, 2, 3];
a.forEach((num) => { console.log(num) });

//결과
//1
//2
//3

이터레이터(Iterator)

이터레이터(iterator)란 반복 처리(iteration)가 가능한 객체를 말합니다. 위의 forEach 메서드의 작업은 내부적으로 처리되므로 개발자는 각 처리 단계를 제어할 수 없습니다.
그러나 ECMAScript 6부터 추가된 이터레이터를 사용하면 개발자가 반복 처리를 단계별로 제어할 수 있습니다.

ES6의 이터레이터는 일반적으로 다음 두 가지 항목을 만족하는 객체입니다.

  • next 메서드를 가진다.
  • next 메서드의 반환값은 value 프로퍼티와 done 프로퍼티를 가진 객체이다. 이때 value에는 꺼낸 값이 저장되고 done에는 반복이 끝났는지를 뜻하는 논리값이 저장된다.
    next 메서드의 반환값이 iterator result 객체여야 한다.

예시

let a = [1, 2, 3];
let iter = a[Symbol.iterator]();
// Symbol.iterator(이터레이터 심벌)는 이터레이터를 반환하는 메서드

console.log(iter.next()); // Object {value: 1, done: false}
console.log(iter.next()); // Object {value: 2, done: false}
console.log(iter.next()); // Object {value: 3, done: false}
console.log(iter.next()); // Object {value: undefined, done: true}
console.log(iter.next()); // Object {value: undefined, done: true}

배열의 이터레이터를 반환하는 함수

function makeIterator(array) {
  let index = 0;
  return {
    next() { // next 메서드
      if ( index < array.length ) {
        return {value: array[index++], done: false}; // next 메서드 반환값
      } else {
        return {value: undefined, done: true}; // next 메서드 반환값
      }
    }
  };
}

const iter = makeIterator(['a', 'b', 'c']);

console.log(iter.next()); // Object {value: 'a', done: false}
console.log(iter.next()); // Object {value: 'b', done: false}
console.log(iter.next()); // Object {value: 'c', done: false}
console.log(iter.next()); // Object {value: undefined, done: true}

반복 가능한 객체와 for/of 문

for/of 문은 다음 두 가지 조건을 만족하는 객체를 반복 처리합니다.

  • Symbol.iterator 메서드를 가지고 있다.
  • Symbol.iterator 메서드는 반환값으로 이터레이터(next 메서드를 가지며, next의 반환값으로 value와 done 프로퍼티를 가진 객체를 반환하는 객체)를 반환한다.

Symbol.iterator 메서드를 가진 객체를 반복 가능(이터러블, iterable)한 객체라고 합니다.

for/of 문 없이 이터레이터를 반복실행

let a = [4, 5, 6];

let iter = a[Symbol.iterator](); // 변수 iter에 이터레이터 대입

while(true) {
  let iteratorResult = iter.next();
  if ( iteratorResult.done === true ) break;
  let v = iteratorResult.value;
  console.log(v); // 4 5 6 이 차례대로 console에 찍힘
}

위의 프로그램을 for/of 문을 사용하여 반복 처리를 자동으로 하도록 만들 수 있습니다. 아래의 프로그램은 위 프로그램과 같은 동작을 합니다

for/of 문 사용

let a = [4, 5, 6];

for (let v of a) console.log(v); // 4 5 6 이 차례대로 console에 찍힘

유의사항

이터레이터(iterator) 객체와 이터러블한(iterable) 객체는 서로 다른 개념의 객체입니다.
이터레이터는 next 메서드를 가지는 반면에, 이터러블한 객체는 Symbol.iterator(이터레이터 심벌) 메서드를 가지기 때문입니다.

상단의 배열의 이터레이터를 반환하는 함수 makeIterator로 생성한 iter이터레이터(iterator) 이지만 for/of 문으로는 순회할 수 없습니다. 왜냐하면 Symbol.iterator(이터레이터 심벌) 메서드를 가지고 있지 않아 이터러블(iterable)한 객체가 아니기 때문이죠.

for (let v of iter) console.log(v); // TypeError: iter is not iterable

주어진 이터레이터를 반복 처리하려면 다음과 같이 이터러블한(iterable) 객체를 생성해주어야 합니다.
Symbol.iterator(이터레이터 심벌) 메서드를 추가하여 새로운 객체를 생성해야 합니다.

let iterable = {};
iterable[Symbol.iterator] = () => iter;
for (let v of iterable) console.log(v); // 'a' 'b' 'c' 를 순서대로 표시한다.
profile
JavaScript, Node.js 그리고 React를 배우는

0개의 댓글