본문 바로가기

TIL✨

iterable error _TIL(44)

이번 프로젝트 중에 자주 보았던 에러 중에 하나인 TypeError : 'nonetype'object is not iterable🔥에 대해서 정리하려고한다.


그래서 iterable이 뭘까부터 시작했다. '순회가능한'뜻을 가지고 있었다.

for...of문을 사용해서 이렇게 값을 하나씩 반환할 수 있다.

const array = [1,2,3];
for(const item of array){  //아이템을 하나씩 출력한다.  1,2,3출력
}

 즉, 순회가 가능하다면 for...of문 사용이 가능하다. =>이게 왜 가능하냐면 iterabor을 반환하는 내장메소드들이 있기 때문이다.

그래서 iterator를 리턴한다는 것은 순회가능한 객체인것을 말한다.(for..of문 ,spread문 사용이 가능하다.)

 

그럼 iterabor을 반환하지 못하면 for..of문을 쓰지 못하는것일까?

그럴때 사용하는 [Symbol.iterator]=function(){} 문이 있다. 이 함수는 iterator을 반환한다. 그러면 for..of 문을 돌릴준비가 되었다.

 

배열,문자열..등은 기본적으로 iterator을 가지고 있지만 객체는 그렇지 않으므로 객체에 사용을 해줄 수 있다.

'객체를 그럼 왜 순회해야하나' 라는 생각을 할 수 있는데 이 때는 어떠한 컬렉션을 가진 객체에서 그 컬렉션을 하나씩 꺼내고 싶을때 사용할 수 있다.

 

이 symbol.interator을 쓰면 반환되는 next함수가 있다.

이 next함수는 {value, done}을 반환한다.

 1.value : 값을 하나씩 뱉는다.

 2.done : 모든 순회가 끝나면 true, 아직 진행중이면 false를 반환한다.

//next예시

const iterator = array.values();  //1,2,3,
for(const item of iterator){
  console.log(item)
}

const iterator = array.values();
console.log(iterator.next( ))     //{value : 1 ,done: false}

 

이 next를 사용해서 

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


range[Symbol.iterator] = function() {
  return {
    current: this.from,
    last: this.to,
    next() {
      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....
}

객체에 for...of문을 돌리게되면 객체에[Symbol.interator]을 통해서 iterator과 next( )을 반환하고 next를 통해서 나온 하나씩의 값을가지고 실행이 된다.

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

//모던자바스크립트

 

코드가 복잡하므로 간단하게 하기 위해서 변수를 지정해서 사용해 줄 수 있다.

const multiple = {
  [Symbol.iterator]() {
    const max = 10;
    let num = 0;
    return {
      next() {
        return { value: num++ , done: num > max };
      },
    };
  },
};

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

 

위에 내용을 활용해서 재사용이 가능하도록 함수로 만들어보자!

function makeIterable(initialValue, maxValue, callback) {
  return {
    [Symbol.iterator]() {
      let num = initialValue;
      return {
        next() {
          return { value: callback(num), done: num > maxValue };
        },
      };
    },
  };
}
const add = makeIterable(0, 10, (n) => {
  n ++;   // +1해주자
});
for (const num of add) {
  console.log(num);   //하나씩 나온 값을 출력하자.
}

이렇게 활용이 가능하다.


그래서 이렇게 공부해서 깨달은 점은

내가 이 오류가 뜰때마다 iterator을 반환하지 못하는 객체들에 대고 값을 하나씩 내놓으라고 나도모르게 코드를 짜고 있었나 보다한다.

iterator을 공부하면서 iterator하지 못하는 객체를 순회가능한 값으로 바꾸는 공부를 했지만 오히려 이 공부를 통해서 프로젝트 중에

내가 가져올 값이 이게 아니구나 하면서 빨리 알아 챌 수 있게 되었다.

아무래도 react로 만들다보니 많은 컴포넌트가 생기고 페이지가 많아지다보니 값들이 헷갈렸었었는데 이젠 아니다...!ㅎ

오늘의 TIL 끝 😎

 

 

 

 

 

 

 

'TIL✨' 카테고리의 다른 글

useEffect_TIL(46)  (0) 2023.01.02
리액트 네이티브_TIL(45)  (0) 2023.01.01
parameter_TIL(42)  (0) 2022.12.28
TIL(41)  (0) 2022.12.26
글 작성페이지 input 나누기 TIL(39)  (0) 2022.12.23