[JavaScript] iterable 객체

ParkCode·2024년 3월 17일
0

자바스크립트

목록 보기
19/20

iterable 객체

반복 가능한(iterable, 이터러블) 객체는 배열을 일반화한 객체입니다. 이터러블 이라는 개념을 사용하면 어떤 객체에든 for..of 반복문을 적용할 수 있습니다.

배열을 일반화한 객체?
배열과 비슷한 형태와 기능을 가지면서도 내부 구현이 다른 객체.
= 반복 가능한 객체(iterable objects)
Array, Map, Set 등은 물론이며 String도 반복 가능

반대로 이터러블이 아닌 객체는 for...of을 적용할 수 없다.
하지만 이러한 객체가 어떤 것들의 컬렉션(목록, 집합 등)을 나타내고 있는 경우, for..of 반복문을 사용할 수 있다면 컬렉션을 순회하는데 유용할 것이다.

Symbol.iterator

for..of를 적용하기에 적합해 보이는 배열이 아닌 객체를 만들고 이 객체를 이터러블로 만들어보자!
예시의 객체 range는 숫자 간격을 나타낸다.

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

// 아래와 같이 for..of가 동작할 수 있도록 하는 게 목표입니다.
// for(let num of range) ... num=1,2,3,4,5

Symbol.iterator(특수 내장 심볼)이라는 메서드를 객체에 추가하면 배열이 아닌 객체에 for...of을 사용할 수 있게 된다.
for..of가 시작되자마자 for..of는 Symbol.iterator를 호출한다.(Symbol.iterator가 없으면 에러)
Symbol.iterator는 반드시 이터레이터(interator)를 반환해야 한다.

1. 이터레이터
: 이터러블 객체를 탐색하는 방법을 정의한 객체. 메서드 next()를 가진다.

2. next()
: 호출 시 이터레이터 내부의 다음 값에 대한 두 프로퍼티 value, done을 반환한다.
{done: Boolean, value: any}의 형태

3. value
: 이터레이터에서 반환된 값

4. done
: 이터레이터 내부의 모든 값을 반환했는지를 나타내는 boolean 값
done=true는 반복이 종료되었음을 의미한다.
done=false일땐 value에 다음 값이 저장된다.

이후 for..of는 반환된 객체(이터레이터)만을 대상으로 동작한다.
for..of에 다음 값이 필요하면, for..of는 이터레이터의 next()를 호출한다.

range를 반복 가능한 객체로 만들어주는 코드

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

// 1. for..of 최초 호출 시, Symbol.iterator가 호출됩니다.
range[Symbol.iterator] = function() {

  // Symbol.iterator는 이터레이터 객체를 반환합니다.
  // 2. 이후 for..of는 반환된 이터레이터 객체만을 대상으로 동작하는데, 이때 다음 값도 정해집니다.
  return {
    current: this.from,
    last: this.to,

    // 3. for..of 반복문에 의해 반복마다 next()가 호출됩니다.
    next() {
      // 4. next()는 값을 객체 {done:.., value :...}형태로 반환해야 합니다.
      if (this.current <= this.last) {
        return { done: false, value: this.current++ };
      } else {
        return { done: true };
      }
    }
  };
};

// 이제 의도한 대로 동작합니다!
for (let num of range) {
  alert(num); // 1, then 2, 3, 4, 5
}

이터러블 객체의 핵심은 '관심사의 분리(Separation of concern, SoC)'에 있다.

  • range엔 메서드 next()가 없다.
  • 대신 rangeSymbol.iterator를 호출해서 만든 ‘이터레이터’ 객체와 이 객체의 메서드 next()에서 반복에 사용될 값을 만들어낸다.

이렇게 하면 이터레이터 객체와 반복 대상인 객체(range)를 분리할 수 있다.

문자열은 이터러블이다

배열과 문자열은 가장 광범위하게 쓰이는 내장 이터러블이다.

for..of는 문자열의 각 글자를 순회합니다.

for (let char of "test") {
  // 글자 하나당 한 번 실행됩니다(4회 호출).
  alert( char ); // t, e, s, t가 차례대로 출력됨
}

서로 게이트 쌍(surrogate pair)에도 잘 동작한다.

let str = '𝒳😂';
for (let char of str) {
    alert( char ); // 𝒳와 😂가 차례대로 출력됨
}

이터레이터를 명시적으로 호출하기

for..of 없이 이터레이터를 직접 호출하여 문자열 순회하기

문자열 이터레이터를 만들고, 여기서 값을 ‘수동으로’ 가져오는 예시이다.

let str = "Hello";

// for..of를 사용한 것과 동일한 작업을 합니다.
// for (let char of str) alert(char);

let iterator = str[Symbol.iterator]();

while (true) {
  let result = iterator.next();
  if (result.done) break;//이터레이터가 모든 값을 순회했으므로 > break
  alert(result.value); // 글자가 하나씩 출력됩니다.
}

이터레이터를 명시적으로 호출하는 경우는 거의 없는데, 이 방법을 사용하면 for..of를 사용하는 것보다 반복 과정을 더 잘 통제할 수 있다는 장점이 있다.

반복을 시작했다가 잠시 멈춰 다른 작업을 하다가 다시 반복을 시작하는 것과 같이 반복 과정을 여러 개로 쪼개는 것도 가능하다.

❇️ 요약

  • for..of을 사용할 수 있는 객체를 이터러블이라고 부른다.
  • 이터러블엔 메서드 Symbol.iterator가 반드시 구현되어 있어야 한다.
  • obj[Symbol.iterator]의 결과는 이터레이터라고 부른다. 이터레이터는 이어지는 반복 과정을 처리한다.
  • 이터레이터엔 객체 {done: Boolean, value: any}을 반환하는 메서드 next()가 반드시 구현되어 있어야 한다.
  • done:true은 반복이 끝났음을 의미하고 그렇지 않은 경우엔 value가 다음 값이 된다.
  • 문자열이나 배열 같은 내장 이터러블에도 Symbol.iterator가 구현되어 있다.
  • 문자열 이터레이터는 서로게이트 쌍을 지원합니다.

참조

iterable 객체

profile
프론트엔드 개발자 지망생

0개의 댓글

관련 채용 정보