이번 프로젝트 중에 자주 보았던 에러 중에 하나인 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 |