본문 바로가기
개발자 도전기/[STUDY] JS || TS

JavaScript | FP && ES6+ | ES6에서의 순회와 이터러블:이터레이터 프로토콜

by 답수 2022. 1. 20.
728x90
SMALL

 

자바스크립트는 ES6부터 리스트 순회 방법에 많은 발전이 있다고 한다.

const list = [1, 2, 3];
const str = 'abc';

// ES5에서 순회 방식
for (var i=0; list.length; i++) {
	console.log(i);
}

for (var i=0; str.length; i++) {
	console.log(i);
}


// ES6에서 순회 방식
for (const a of list) {
	console.log(a);
}

for (const a of str) {
	console.log(a);
}

 

ㅇㅅㅇ... 나도 지금까지 ES5 때 for문을 자주 사용하고 있었다.. 물론 forEach, map 등의 함수들도 사용하긴 하지만... ES6 이후의 저 순회 방식을 사용한 기억이 없다.. 좋은 것 배워갑니댜..

 

 

이터러블:이터레이터 프로토콜

이터러블/이터레이터 프로토콜은 이터러블을 for...of, 전개 연산자 등과 함께 동작하도록 하는 규약이다.

  • 이터러블: 이터레이터를 리턴하는 [Symbol.iterator]()를 가진 값
  • 이터레이터: {value, done} 객체를 리턴하는 next()를 가진 값

array와 set, map을 통해 더 자세히 알아봅시다.

 

Array

const arr = [1, 2, 3];
for (const a of arr) console.log(a);

배열은 키와 값을 가지게 되기 때문에 인덱스를 활용할 수 있다. arr[0]일 때 1, arr[1]일 때 2 처럼

 

Set

const set = new Set([1, 2, 3]);
for (const a of set) console.log(a);

Set은 배열과 달리 키값이 없다. 즉 인덱스 활용이 불가능하다. set[0]을 입력하면 undefined가 리턴!

즉 배열과는 다른 for문으로 추상화되어 있다.

 

Map

const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
for (const a of map.keys()) log(a);     // key값만 반환
for (const a of map.values()) log(a);   // value값만 반환
for (const a of map.entries()) log(a);  // 키, 밸류 반환
for (const a of map) log(a);  // 키, 밸류 반환

 

 

Symbol은 어떤 객체의 키가 될 수 있다. Symbol.iterator는 객체의 이터레이터를 반환하는 메서드로 for...of에서 사용된다.

let iter1 = arr[Symbol.iterator]();
console.log(iter1.next());		// { value: 1, done: false }
console.log(iter1.next());		// { value: 2, done: false }
console.log(iter1.next());		// { value: 3, done: false }
console.log(iter1.next());		// { value: undefined, done: true }


let iter2 = set[Symbol.iterator]();
console.log(iter2.next());		// { value: 1, done: false }
console.log(iter2.next());		// { value: 2, done: false }
console.log(iter2.next());		// { value: 3, done: false }
console.log(iter2.next());		// { value: undefined, done: true }

 

 

ES6 이후부터 순회는 이터러블:이터레이터 프로토콜을 따르기 때문에 매우 중요하다고 한다! 다음은 사용자 정의 이터러블을 통해 더 자세히 알아보자.

const iterable = {
	[Symbol.iterator]() {
        let i = 3;
        return {
            next() {
            return i == 0 ? {done: true} : {value: i--, done: false};
            },
            [Symbol.iterator]() {  // 이전까지 진행됐던 상테에서 next를 진행할 수 있도록. 이 코드 없으면 TypeError: iterator is not iterable 
                return this;
            }
        }
    }
};

let iterator = iterable[Symbol.iterator]();
for (const a of iterator) console.log(a);

 

 

이터러블:이터레이터 프로토콜에 대해 한 번 더 파보자. 개념적으로 뭔가 더 알고 싶네

MDN docs - Iteration protocols

 

Iteration protocols - JavaScript | MDN

ECMAScript 2015 (ES6)에는 새로운 문법이나 built-in 뿐만이 아니라, protocols(표현법들)도 추가되었습니다. 이 protocol 은 일정 규칙만 충족한다면 어떠한 객체에 의해서도 구현될 수 있습니다.

developer.mozilla.org

 

이터러블 프로토콜(The iterable protocol)

위에서 이터러블은 이터레이터를 리턴하는 [Symbol.iterator]()를 가진 값이라고 정의했었다. 

이터러블 프로토콜은 자바스크립트 객체들이 for..of 구조에서의 value들이 loop되는 것과 같은 이터레이션 동작을 정의하거나 사용자 정의하는 것을 허용하는 것이고, 이터러블 하기 위해서는 객체는 @@iterator 메소드를 구현해야 한다. 이것은 객체가 Symbol.iterator key의 속성을 가져야 한다는 것을 의미한다.

 

Property Value
[Symbol.iterator] object를 반환하는, arguments 없는 function. iterator protocol을 따른다.

 

어떠한 객체가 반복되어야 한다면 이 객체의 @@iterator 메소드가 인수없이 호출되고, 반환된 이터레이터는 반복을 통해 획득할 값들을 얻을 때 사용된다.

 

그럼 이터레이터 프로토콜은 뭐여?

 

이터레이터 프로토콜(The iterator protocol)

이터레이터 프로토콜은 value들의 sequence를 만드는 표준 방법을 정의한다.

객체가 next() 메소드를 가지고 있고, 아래의 규칙에 따라 구현되었다면 그 객체는 이터레이터다.

 

Property Value
next 아래 2개의 속성들을 가진 object를 반환하는 arguments가 없는 함수

  - done (doneblean)
    - Iterator(반복자)가 마지막 반복 작업을 마쳤을 경우 true
      만약 이터레이터에 return값이 있다면 value의 값으로 지정
    - 이터레이터의 작업이 남아있을 경우 false.
  - value
    - 이터레이터로부터 반환되는 모든 자바스크립트 값. done이 true일 경우 생략될 수 있음

 

위에서 예시로 들었던 array, set, map 모두 내장 iterable이다.

728x90
LIST

댓글