본문 바로가기

JAVASCRIPT

<JAVASCRIPT> 이터러블이란? iterable / iterator

 

 

 

 

지난 글 제너레이터에 짝궁같은 느낌으로 이터러블이라는 놈이 있다고 한다.

 

일단 이터러블에 대해서 개념부터 알아보자

 

이터러블(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)

 

 

 

 

 

> 결과값

 

 

흠... 객체에 이터레이터를 추가해주는 것처럼 보인다. 이건 질문을 해야겠다.

 

 

 

 

 

728x90