지난 글 제너레이터에 짝궁같은 느낌으로 이터러블이라는 놈이 있다고 한다.
일단 이터러블에 대해서 개념부터 알아보자
이터러블(iterable )과 이터레이블(iterable)이란?
- iterable : 반복가능한 객체, 배열을 일반화한 객체이다. 이터러블이라는 개념을 사용하면 어떤 객체에든 for ~of 반복문을 사용할 수 있다.
배열이 대표적인 이터러블이며 배열외의 다수의 내장 객체가 반복 가능하다. 문자열 역시 이터러블의 예시이다.
- iterable/iterator protocol : iterable 을 for of, 스프레드 연산자 등과 함께 동작하도록 한 규약
- javascript의 Array, set, map은 iterable/iterator protocol 을 따르고 있다.
아.... 그러니까 반복문을 적용할 수 있으면 이터러블 객체라고 할 수 있는 건가? 아니면 for of를 사용할 수 있게 해주는 키워드가 있는 건가? 아직 조금 아리송하다. 예시를 보면서 알아가보자
짠
let one = {
from: 1,
to : 5
}
let myarr = [1,2,3]
이렇게 숫자 간격을 나타내는 one이라는 객체와 배열이 있다. 범위 내의 숫자를 모두 출력하려면 어떻게 해야할까?
이 코드가 작동하도록 하려면??
for(let num of one){
console.log(num)
}
+) 그냥 객체로 돌리면 에러가 뜬다
먼저 one이라는 객체를 이터러블로 만들려면 객체에 Symbol.iterator(특수내장 심볼)라는 메서드를 추가해야한다.
이걸 추가하면 for~of 가 동작한다고 한다.
1. for~of 가 시작되자마자 for~of 는 Symbol.iterator를 호출한다. 그리고 Symbol.iterator 는 반드시 이터레이터를 반환해야한다.
2. 이후 for~of는 반환된 객체(이터레이터)만을 대상으로 동작한다.
3. for~of에 다음값이 필요하다면 for~of는 이터레이터의 next() 메서드를 호출한다.
4. next()의 반환 값은 {done: Boolean, value: any } 와 같은 형태여야 한다.
(done == true 면 반복이 종료되었다는 뜻, done == false면 value에 다음 값이 저장된다.)
먼저 배열일때 어떻게 쓰는지 보자
예시 1 - 배열
const myarr = [1, 2, 3]
let iterator = myarr[Symbol.iterator]()
for(const i of iterator){
console.log(i);
}
결과값은??
오 잘나온다!!!
+) 만약 하나 건너뛰고 출력하려면 next()를 쓰면된다.
const myarr = [1, 2, 3]
let iterator = myarr[Symbol.iterator]()
iterator.next();
for(const i of iterator){
console.log(i);
}
> 결과
예시2 - 객체일때
let one = {
from: 1,
to : 5
}
// 시작하자마자
one[Symbol.iterator] = function(){
return {
current : this.from, // this는 one을 가리킴
last : this.to,
next(){ // next() 함수 호출, 리턴 형태가 {done:~, value:~} 여야 한다.
if(this.current <= this.last){
return {done: false, value : this. current++ };
}else {
return { done : true }
}
}
};
};
for(let num of one){
console.log(num);
}
one 이라는 객체에 는 next()라는 메서드가 없기 때문에
one[Symbol.iterator]() 를 사용해서 이터레이터를 반환하게 하고 그 안에서 next()를 호출한 것이다.
> 결과값
오 이제 원하는대로 나왔다!
+) 설명에
??? 이터러블 객체의 핵심은 '관심사의 분리'라는 말이 있던데
그렇다면 참조값을 복사해서 변경하는 걸까? 아니면 그 주소에 있는 값자체를 변경하는 걸까?
궁금해서 콘솔을 찍어봤다.
let one = {
from: 1,
to : 5
}
console.log(one)
console.dir(one)
// 시작하자마자
one[Symbol.iterator] = function(){
return {
current : this.from, // this는 one을 가리킴
last : this.to,
next(){ // next() 함수 호출, 리턴 형태가 {done:~, value:~} 여야 한다.
if(this.current <= this.last){
return {done: false, value : this. current++ };
}else {
return { done : true }
}
}
};
};
for(let num of one){
console.log(num);
}
console.log(one)
console.dir(one)
> 결과값
흠... 객체에 이터레이터를 추가해주는 것처럼 보인다. 이건 질문을 해야겠다.
'JAVASCRIPT' 카테고리의 다른 글
<Javascript> 프로퍼티 조회와 변수 호이스팅 (0) | 2025.05.05 |
---|---|
<JAVASCRIPT> 호이스팅?? let과 const는 호이스팅이 된다? 안된다? (0) | 2023.07.03 |
<JAVASCRIPT> 제너레이터(Generator)란? / 제너레이터와 일반함수의 동작차이 / next() (0) | 2023.04.05 |
< JAVASCRIPT> 이벤트가 바인딩 되어있는지 확인하기 / 이벤트 확인하기 / addEventListener란? (0) | 2023.04.05 |
<JAVASCRIPT> JS에서 이벤트란? 이벤트 리스너? (0) | 2023.04.04 |