33. 자료구조 - iterable 객체

Chipmunk_jeong·2021년 3월 17일
0

TIL

목록 보기
33/62
post-thumbnail

iterable객체란?
배열을 일반화 한 객체이다.
이터러블이라는 개념을 사용하면 어떤 객체든 for..of반복문을 사용할 수 있다.

배열은 이터러블객체중 대표적이다.
또한 문자열도 이터러블이다.
배열이 아닌 객체중에 컬렉션을 나타내는 객체일 경우,
for..of문버을 적용할 수만 있다면 컬렉션을 순회하는데 유용할 것이다.


Symbol.iterator

객체에 Symbol.iterator(특수 내장 심볼)이라는 메서드를 추가해 아래와 같은 일이 발생하게 한다.

  • for..of가 시작되자마자 Symbol.iterator를 호출한다.
    (Symbol.iterator가 없으면 에러가 남)
    또한 Symbol.iterator는 반드시 이터레이터를 반환해야 함
  • 이후 for..of는 반환된 객체만을 대상으로 동작
  • for..of에 다음 값이 필요하면, for..of는 이터레이터의 next()메서드를 호출한다.
  • next()의 반환값은 {done: Boolean, value: any}와 같은 객체의 형태여야 한다. done=true는 반복이 종료 되었음을 의미, done=false일땐 value에 다음값이 저장된다.

아래의 예제를 한번 보자.

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) {
  console.log(num); // 1, then 2, 3, 4, 5
}

이터러블 객체는 관심사의 분리에 있다.

  • range엔 메서드 next()가 없다.
  • rangeSymbol.iterator를 호출해서 만든 이터레이터 객체와 이 객체의 메서드 next()에서 반복에 사용될 값을 만들어 낸다.
let rage = {
  from: 1,
  to: 5,

  [Symbol.iterator]() {
    this.current = this.from;
    return this;
  },

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

for (let num of range) {
  console.log(num); // 1, then 2, 3, 4, 5
}

많은 이터레이터

무수히 많은 이터레이터도 가능하다.
range에서 range.to에 Infinity를 할당한다면 range가 무한대가 된다.
많은 난수를 생성하는 이터러블 객체를 만드는게 가능하다.

next에는 제약사항이 없다. next가 값을 계속 반환하는 것은 정상적인 작동이다. 그리고 beak를 활용하면 반복을 멈출 수 있다.


문자열은 이터러블

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

for(let char of "hello") {
  console.log(char); // 'h', 'e', 'l', 'l', 'o'
}

이터레이터의 명시적 호출

for..of를 사용했을 때와 동일한 방법으로 문자열을 순회 할 때, 직접 호출을 통해 순회를 해보자.


let str = "Code";

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

while (true) {
  let result = iterator.next();
  if(result.done) { break; }
  console.log(result.value);
}

이렇게 명시적으로 호출하는 경우는 드문데 이 방법을 사용하면 반복과정을 좀더 잘 통제할 수 있다.
반복을 시작했다가 잠시 멈춰 다른작업을 하다가 다시 반복을 시작하는 것과 같이 여러개로 쪼개는 것이 가능하다.


유사 배열

이터러블과 비슷해보지이만 많이 다른 용어이다.

  • 이터러블은 위에서 보듯이 Symbol.iterator가 구현된 객체
  • 유사 배열은 인덱스와 length 프로퍼티가 있어 배열처럼 보이는 객체

자바스크립트를 사용해 문제를 해결할 때 이터러블 객체나 유사 배열 객체 또는 둘다인 객체를 만날 수 있다.

이 두가지를 다 가지고 있는것중 대표적인게 문자열이다.

하지만, 이터러블 객체라고 해서 유사배열인것은 아니다.
그리고 유사배열이라고 해서 이터러블 객체가 아니다

이터러블과 유사배열은 대개 배열이 아니기 때문에 push, pop등의 배열 메서드를 지원하지 않는다.

Array.from

범용 메서드 Array.from은 이터러블이나 유사배열을 인자로 받아 진짜 배열로 만들어준다.

let arrayLike = {
  0: 'Hello',
  1: 'world',
  length: 2,
};

let arr = Array.from(arrayLike);
console.log(arr.pop()); // 'world'
profile
Web Developer

0개의 댓글