I. 이터러블 프로토콜 iterable protocol
- 반복, 순회 기능을 사용하는 주체간의 통일된 규격
- 공통 기능들:
for ... of
, 스프레드 문법, 배열 디스트럭쳐링 - 👉 MDN 문서 보기
이터러블 iterable - 이터러블 프로토콜을 준수하는 객체
- 배열, 문자열,
Set
,Map
,arguments
등... - 키
Symbol.iterator
( well-known 심볼 ) 의 값으로 이터레이터를 반환하는 메서드를 가짐 - 👉 Well-known 심볼 MDN 문서 보기
console.log(
[][Symbol.iterator],
''[Symbol.iterator],
new Set()[Symbol.iterator],
new Map()[Symbol.iterator]
);
// 다른 타입의 인스턴스에는 없음
console.log(
(1)[Symbol.iterator],
(true)[Symbol.iterator],
{ x: 1 }[Symbol.iterator]
);
실행시 이터레이터 반환
console.log(
[][Symbol.iterator](),
''[Symbol.iterator](),
new Set()[Symbol.iterator](),
new Map()[Symbol.iterator]()
);
II. 이터레이터 iterator
next
메서드를 통해 이터러블을 순회하며 값을 반환
const arr = [1, 'A', true, null, {x: 1, y: 2 }];
const arrIterator = arr[Symbol.iterator]();
// 펼쳐서 메서드 살펴볼 것
console.log(arrIterator);
console.log(
arrIterator.next
);
arrIterator.next(); // ⭐ 반복 실행해 볼 것
이터레이터 프로토콜 iterator protocol
next
메서드의 반환 객체 내 요소
value
- 해당 차례에 반환할 값done
- 순회 종료 여부 ( 마지막 값 반환 다음 차례부터 )
III. 이터러블 만들어보기
예제 1. 🎲 주사위를 열 번 굴리는 이터러블
const diceTenTimes = {
// ⭐️ 아래의 메서드를 갖는 것이 이터러블 프로토콜
[Symbol.iterator] () {
let count = 0;
let maxCount = 10;
// ⭐️ 이터레이터(next 메서드를 가진 객체)을 반환
return {
next () {
return {
value: Math.ceil(Math.random() * 6),
done: count++ >= maxCount
}
}
}
}
}
const diceIterator = diceTenTimes[Symbol.iterator]();
for (let i = 0; i < 12; i++) {
console.log(
diceIterator.next()
);
}
// 💡 for ... of 문 사용 가능
for (const num of diceTenTimes) {
console.log(num);
}
// 💡 스프레드 문법 사용 가능
const diceResults = [...diceTenTimes];
console.log(diceResults);
// 💡 배열 디스트럭쳐링 사용 가능
const [first, second, ...rest] = diceTenTimes;
console.log(
'주사위의 첫번째, 두번째 숫자는 각각 '
+ `${first}(와)과 ${second}, 나머지의 합은 ${
rest.reduce((a, b) => a + b)
} 입니다.`
);
예제 2. 🧮 피보나치 이터러블
function fiboIterator () {
let count = 0;
const maxCount = 10; // 최대 횟수가 지정됨
let [x, y] = [0, 1];
return {
next () {
[x, y] = [y, x + y];
return { value: y, done: count++ >= maxCount }
}
}
}
const fibonacci = {
[Symbol.iterator]: fiboIterator
}
for (num of fibonacci) {
console.log(num);
}
⭐️ 원하는 최대 횟수의 피보나치 이터러블 생성하기
function getFiboWithMax (maxCount) {
return {
[Symbol.iterator] () {
let count = 0;
let [x, y] = [0, 1];
return {
next () {
[x, y] = [y, x + y];
return { value: y, done: count++ >= maxCount }
}
}
}
}
}
const fiboMax5 = getFiboWithMax(5);
const fiboMax20 = getFiboWithMax(20);
console.log([...fiboMax5]);
console.log([...fiboMax20]);
예제 3. ⌛️ 순번 이터러블 X 이터레이터
💡 이터러블의 역할도 하는 이터레이터 만들기
function workersIter (people) {
let idx = 0;
return {
// 💡 이터레이터로서 [스스로]를 반환!
// 사장: 직원은 나다.
[Symbol.iterator] () { return this; },
// 직원의 역할
next () {
return {
value: people[Math.min(idx, people.length - 1)],
done: idx++ >= people.length
};
}
}
}
// 이터러블로 사용
// 인원 명단 확인
const team1 = [
'철수', '영희', '돌준', '미나', '준희'
];
let workersIter1 = workersIter(team1);
console.log(
[...workersIter1]
);
// ⚠️ 이터레이터를 겸하는 경우 한 번 순회하면 끝
console.log(
[...workersIter1]
);
// 새로 생성해야 다시 순회
workersIter1 = workersIter(team1);
console.log(
[...workersIter1]
);
// 이터레이터로 사용
// 인원 순번 넘기기
function switchWorker(iter) {
const next = iter.next();
console.log(
next.done
? '-- 인원 없음 -- '
: `${next.value} 차례입니다.`
);
}
workersIter1 = workersIter(team1);
switchWorker(workersIter1); // ⭐ 반복 실행해 볼 것