이터레이션 프로토콜
•
ES6에서 도입
•
순회 가능한 데이터 컬렉션을 만들기 위한 규칙
•
이터레이션 프로토콜을 준수하는 이터러블은 for ... of문, 스프레드 문법, 배열 디스트럭처링 할당의 대상으로 사용 가능
•
이터레이션 프로토콜 종류
◦
이터러블 프로토콜
▪
Symbol.iterator 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속받은 Symbol.iterator 호출 시 이터레이터 프로토콜을 준수한 이터레이터를 반환
--> 이터러블 프로토콜(for..of, 스프레드, 디스트럭처링 할당의 대상으로 사용 가능)
◦
이터레이터 프로토콜
▪
Symbol.iterator 메서드 호출 시 이터레이터 프로토콜을 준수한 이터레이터를 반환.
▪
이는 next 메서드를 소유
▪
next 메서드 호출 시 value와 done프로퍼티를 갖는 이터레이터 리절트 객체를 반환
이터레이터
▪
이터레이터 프로토콜을 준수한 객체
▪
이터러블 요소를 탐색하기 위한 포인터 역할!
[Symbol.iterator]() { ... } // --> 이터러블
// 위 Symbol.iterator가 return 시 아래의 이터레이터 반환
// 이터레이터
{
next() {
return { value: any, done: boolean }; // 이터러블 result 객체
}
}
TypeScript
복사
이터러블
•
이터러블 인지 확인
const isIterable = v => v!== null & typeof v[Symbol.iterator] === 'function';
TypeScript
복사
•
배열은 Array.prototype으로 Symbol.iterator 메서드를 상속 받아 for ... of 문, 스프레드 문법, 배열 디스트럭처링 할당의 대상으로 사용 가능
•
이 Symbol.iterator를 직접 구현하지 않거나 상속받지 않은 일반 객체는 사용 불가
이터레이터
•
Symbol.iterator 메서드 호출 시 이터레이터를 반환하는데 이 이터레이터는 next 메서드를 갖는다.
•
next는 각 요소를 순회하기 위한 포인터의 역할.
•
next 메서드 호출 시 이터러블을 순차적으로 한 단계씩 순회하며 결과를 나타내는 이터레이터 리절트 객체 반환
•
리절트 객체의 value 프로퍼티는 현재 순회중인 이터러블 값을, done 프로퍼티는 이터러블 순회 완료 여부를 나타냄
빌트인 이터러블
빌트인 이터러블 | Symbol.iterator 메서드 |
Array | Array.prototype[Symbol.iterator] |
String | String.prototype[Symbol.iterator] |
Map | Map.prototype[Symbol.iterator] |
Set | Set.prototype[Symbol.iterator] |
TypedArray | TypedArray.prototype[Symbol.iterator] |
arguments | arguments.prototype[Symbol.iterator] |
DOM 컬렉션 | NodeList, HTML.prototype[Symbol.iterator] |
for ... of 문
•
for ... in 문 --> 객체의 프로토타입 체인상에 존재하는 모든 프로퍼티 중 [[Enumerable]] 값이 true인 프로퍼티를 순회하며 열거. (심벌 제외)
•
for .. of 문 --> 내부적으로 이터레이터의 next 메서드를 호출하여 이터러블 순회하며 next 메서드가 변환한 이터레이터 리절트 객체의 value 프로퍼티 값을 for ... of문 변수에 할당. (done이 true면 이터러블 순회 종료)
이터러블과 유사 배열 객체
•
유사 배열 객체는 이터러블이 아닌 일반 객체여서 Symbol.iterator 메서드가 없고, for ... of 문으로 순회 불가능
이터레이션 프로토콜의 필요성
•
ES6 이전의 순회 가능한 데이터 컬렉션들은 통일된 규약 없이 for, for...in, forEach 등으로 다양한 방법으로 순회를 함. --> 이터레이션 프로토콜을 준수하는 이터러블로 통일해 for ... of, 스프레드, 배열 디스트럭처링 할당의 대상으로 사용할수 있도록 일원화(더 효율적이다)
•
이터레이션 프로토콜 : 데이터 소비자와 데이터 공급자를 연결하는 인터페이스 역할.
사용자 정의 이터러블
사용자 정의 이터러블 구현
피보나치 수열 사용자 정의 이터러블
const fibonacci = {
[Symbol.iterator]() {
let [pre, cur] = [0, 1];
const max = 10;
return {
next() {
[pre,cur] = [cur, pre + cur];
return { value: cur, done: cur >= max };
}
};
}
};
for (const num of fibonacci) {
console.log(num);
}
TypeScript
복사
이터러블을 생성하는 함수
•
수열의 최대값을 인수로 전달받아 이터러블을 반환하는 함수로 만들면 된다.
const fibonacciFunc = function(max) {
...
return {
[Symbol.iterator]() {
return {...};
}
};
};
TypeScript
복사
이터러블이면서 이터레이터인 객체를 생성하는 함수
•
이터레이터를 생성하려면 Symbol.iterator 메서드를 호출해야함
•
이터러블이면서 이터레이터인 객체
{
[Symbol.iterator]() { return this; },
next() {
return { value: any, done: boolean };
}
}
Plain Text
복사
이터러블이면서 이터레이터인 객체는 Symbol.iterator 메서드를 호출하지 않아도 next 메서드 사용 가능.
그러나 일반적인 이터러블인 객체는 next메서드를 사용하기 위해서는 const iterator = [Symbol.iterator](); 와 같이 한번 호출해야함
무한 이터러블 지연 평가
•
done 프로퍼티 생략시 무한 이터러블 생성 가능
•
이터러블은 지연 평가를 통해 데이터를 생성하므로 for ... of 문이나 배열 디스트럭처링 할당 등이 실행되기 이전까지 데이터 생성 X --> for ... of 의 경우 next 메서드 호출 전까지 데이터 생성 하지 않음
•
-> 불필요한 데이터를 미리 생성하지 않고 필요한 데이터를 필요한 순간에 생성하여 빠른 실행 속도, 불필요한 메모리 소비를 하지 않고 무한도 표현가능