이터러블
순회 가능한 자료구조를 만들기 위해 미리 약속한 규칙
이터러블로 통일하여 for of, 스프레드, 배열 디스트럭처링 할당의 대상으로 쓸 수 있도록 일원화.
이터러블
const isIterable = v => v !== null && typeof v[Symbol.iterator] === 'function';
// 배열, 문자열, Map, Set 등은 이터러블이다.
isIterable([]); // true
isIterable(''); // true
isIterable(new Map()); // true
isIterable(new Set()); // true
isIterable({}); // false
일반 객체도 이터러블 프로토콜을 준수하도록 구현하면 이터러블이 됨.
이터레이터
이터러블의 Symbol.iterator 메서드가 반환한 이터레이터는 next 메서드를 갖는다.
// 배열은 이터러블 프로토콜을 준수한 이터러블이다.
const array = [1, 2, 3];
// Symbol.iterator 메서드는 이터레이터를 반환한다. 이터레이터는 next 메서드를 갖는다.
const iterator = array[Symbol.iterator]();
// next 메서드를 호출하면 이터러블을 순회하며 순회 결과를 나타내는 이터레이터 리절트 객체를 반환한다.
// 이터레이터 리절트 객체는 value와 done 프로퍼티를 갖는 객체다.
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
빌트인 이터러블
Array, String, Map, Set, TypedArray, arguments, DOM 콜렉션(NodeList, HTMLCollection)
for of문
for in은 Enumerable 값이 true인 객체를 순회
for of는 이터러블을 순회
이터러블과 유사 배열 객체
기본적으로 유사 배열 객체는 이터러블이 아니기 때문에 for of가 안됨.
arguments, NodeList, HTMLCollection은 유사 배열 객체이면서 이터러블이라 가능.
Array.from으로 배열로 간단히 변환
// 유사 배열 객체
const arrayLike = {
0: 1,
1: 2,
2: 3,
length: 3
};
// Array.from은 유사 배열 객체 또는 이터러블을 배열로 변환한다.
const arr = Array.from(arrayLike); // arrayLike, mapFn, thisAg
console.log(arr); // [1, 2, 3]
Array.from을 이용해 객체로 이루어진 배열 중복 제거 -> arrayFrom.js 참고
이터레이션 프로토콜의 필요성
이터레이션 프로토콜은 다양한 데이터 공급자가 하나의 순회 방식을 갖도록 규정하여 데이터 소비자가 효율적으로 다양한 데이터 공급자를 사용할 수 있도록 데이터 소비자와 데이터 공급자를 연결하는 인터페이스의 역할을 한다.
사용자 정의 이터러블
이터러블 객체는 range다. 왜냐하면 Symbol.iterator메서드를 가지고 있기 떄문
이터레이터 객체는 Symbol.iterator() 메서드에서 리턴한 객체가 바로 이터레이터다. 왜냐하면 이 객체 안에는 **{value : 값 , done : true/false}**를 리턴하는 next()메서드가 있기 때문이다.
//이터러블 + 이터레이터 구현하기
let range = {
from: 1,
to: 5,
[Symbol.iterator]() { // 생성자
this.current = this.from;
this.last = this.to;
return this; // 자기 자신을 반환. 자기자신엔 next()메소드가 정의되어있으니, next()메소드
// 에서의 this는 생성자로 생성된 객체를 가리키게 된다.
},
next() { // 아예 객체안에 next()메서드를 정의.
if (this.current <= this.to) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
for (let num of range) {
alert(num); // 1, 2, 3, 4, 5
}
// 무한 이터러블을 생성하는 함수
const fibonacciFunc = function () {
let [pre, cur] = [0, 1];
return {
[Symbol.iterator]() { return this; },
next() {
[pre, cur] = [cur, pre + cur];
// 무한을 구현해야 하므로 done 프로퍼티를 생략한다.
return { value: cur };
}
};
};
// fibonacciFunc 함수는 무한 이터러블을 생성한다.
for (const num of fibonacciFunc()) {
if (num > 10000) break;
console.log(num); // 1 2 3 5 8...4181 6765
}
// 배열 디스트럭처링 할당을 통해 무한 이터러블에서 3개의 요소만 취득한다.
const [f1, f2, f3] = fibonacciFunc();
console.log(f1, f2, f3); // 1 2 3
지연평가를 통해 데이터를 생성. (필요할대 생성하는 기법)
'공부공부 > JS 딥다이브' 카테고리의 다른 글
[js 딥다이브] 36장 디스트럭처링 할당 (0) | 2024.02.18 |
---|---|
[js 딥다이브] 35장 스프레드 문법 (0) | 2024.02.15 |
[js 딥다이브] 33장 Symbol (0) | 2024.02.15 |
[js 딥다이브] 32장 String (0) | 2024.02.15 |
[js 딥다이브] 31장 RegExp (0) | 2024.02.15 |