함수형 프로그래밍(사용자 정의 이터러블)

사용자 정의 이터러블, 이터레이터 구현

1.이터러블은 [Symbol.iterator] () 메소드를 가지고 있어야 한다.

const iterable = {
  [Symbol.iterator](){
  }
}

2. [Symbol.iterator] () 메소드는 이터레이터를 반환해야한다. 이 이터레이터는 next ()  메소드를 가지고 있어야 한다.

const iterable = {
  [Symbol.iterator](){
    return{
      next()
    }
  }
}

3. next ()  메소드는 value와 done을 key갑으로 가지는 객체를 리턴해야 한다.

// 여기서는 1,2,3 value를 가지는 이터러블로 진행
const iterable = {
  [Symbol.iterator](){
    let i=3
    return{
      next(){
        return i === 0 ? {done : true} :{ value : i-- , done : false }
      }
    }
  }
}

4. 만든 이터러블로 이터레이터 만들기

const iterator = iterable[Symbol.iterator]() 

만든 이터러블의 Symbol.iterator() 메소드를 이용하여 이터레이터를 생성한다.

log(iterator.next()) // {value : 3, done : false}
log(iterator.next()) // {value : 2, done : false}
log(iterator.next()) // {value : 1, done : false}
log(iterator.next()) // {done : false}

이렇게 만든 이터레이터는 next() 메소드를 통해서 내부의 값을 조회 할 수 있고

for (const a of iterable ) log (a) // 3 2 1, iterator 조회 한거 아님!

for..of 문에서 순회 할 수 있다.

정리하면 이터러블에 Symbol.iterator() 메소드가 구현 되어있기 때문에 for…of 문에 들어갈 수 있고, 내부적으로 next() 메소드가 실행되어 리턴되는 value값이 for…of문의 a값에 들어가게 된다.

하지만 이터러블을 통해 만든 이터레이터는 for of 문 순회가 되지 않는다.

for (const b of iterator ) log (b) // iterator is not iterable

5. Well-formed 이터러블 만들기

잘 구현된 이터러블은

  • 이터러블의 [Symbol.iterator] () 메소드를 통해 만든 이터레이터가 for..of문을 순회 할 수 있다
  • next() 메소드를 통해 일부 진행 했을 때 진행한 이후의 값들로만 순회 할 수 있다.

이 말은 [Symbol.iterator] () 메소드를 통해 만든 이터레이터 역시 [Symbol.iterator] () 메소드를 갖고 있다는 말이다. 그리고 이 메소드를 실행한 값은 자기 자신이라는 말이다.

const arr = [1, 2, 3]
let iterator = arr[Symbol.iterator]()
let it2 = iterator[Symbol.iterator]()
log(it2 === iterator) // true

이렇게 이터레이터가 자기 자신을 반환하는 심볼 이터레이터 메소드를 가지고 있을 때 well-formed 이터레이터, well-formed 이터러블 이라고 할 수 있다.

이를 위 이터러블에 적용 해보자.

const iterable = {
  [Symbol.iterator](){
    let i = 3
    return{
      next(){
        return i === 0 ? { done : true} : {value : i-- , done : false} 
      },
      //만들어진 iterator가 [Symbol.iterator]() 메소드를 갖고 있어야함
      [Symbol.iterator](){ return this }
    }
  }
}

이렇게 이터러블을 정의 한다면 이터러블을 통해 만들어진 이터레이터도 이러터블 이기 떄문에 for..of문 순회가 가능하다.

const iterator = iterable[Symbol.iterator]()
for(const a of iterator) log(a) // 3 2 1 

Written by@[HongDongUk]
공부한 것을 소소하게 적는 블로그.

GitHubFacebook