david's daily developer note

[FE] JavaScript Iterator and iterable protocols 본문

[Develop] Web/Front-end

[FE] JavaScript Iterator and iterable protocols

mouse-david 2022. 6. 19. 18:02
728x90

for...of
반복 가능한 객체의 리스트 순회를 위하여 사용 (Array,Map,Set,String.TypeArray,Arguments.. etc)
반복 가능한 iterable 객체는 배열을 일반화한 객체이고, 이터러블 개념을 사용하면, 어떤 객체든 
for...of 반복문을 적용할 수 있다.

<script>
    let list = [1, 2, 3];
    for (var i = 0; i < list.length; i++) {console.log(list[i]);}
    
    let str = 'string';
    for (var i = 0; i < str.length; i++) {console.log(list[i]);}
    
    for (let n of list) {
    	console.log(n);
    }
    for (let s of str) {
    	console.log(s);
    }
</script>

이터러블은 이터레이터를 반환하는 [Symbol.iterator] () 를 가진 값이다.
for..of가 시작되면, for..of는 Symbol.iterator를 호출하는데, 없다면 에러가 발생한다. 
Symbol.iterator는 반드시 next가 있는 객체의 iterator를 반환해야한다.

여기서 iterator는 {value, done} 객체를 리턴하는 next()를 가진값이다.
이터러블/이터레이터 프로토콜이란 이터러블을 for...of, 전개 연산자 등과 함께 동작하도록 규약한것이다.

<script>
    let set = new Set([1,2,3]);
    for (const s of set) console.log(s);
</script>

for...of는 set의 iterator()를 호출하고, iterator가 호출하는 values는 다시 iterator를 호출한다.

<script>
    let map = new Map([['david', 33], ['ted', 29], ['monkey', 15]]);
    for (const name of map) console.log(name);
</script>

map의 경우에도 keys함수가 values에 key만을 담아서 iterator를 반환하여, for..of가 동작한다.

사용자 정의 이터러블

Symbol Iterator 직접 구현할 수 있다.
well-formed iterable : 잘만든 이터레이터는 자신의 순회중인 포인트를 기억할 수 있어야 한다.

[Symbol.Iterator]() {return this}
<script>
    let iterable = {
    	[symbol.iterator]() {
            let count = 0;
                return {
            	    next() {
                        return count == 10 ? {done : true} : { done: false, value: this.count++ };
                    },
                    [symbol.iterator]() { return this; }
            	}
            }
    	};
    let counter = iterable[Symbol.iterator]();
    for (const cnt of counter) { console.log(cnt); }
</script>

이터러블 객체의 핵심은 관심사의 분리(Separation of concern, Soc)이다.
예시에서, counter는 next 메서드가 없다. counter[Symbol.iterator]() 를 호출해서 만든 이터레이터 객체와, 메서드 next()에서 반복하여 사용할 값을 만든다. 이런식으로 이터레이터 객체인 counter와 반복 대상인 객체를 분리할 수 있다. 

<script>
    const arr = [1, 2];
    console.log([...arr]);
</script>

이터러블/이터레이터 프로토콜을 사용하는 모든 객체는 전개 연산자 사용이 가능하다.

728x90