
ES6에서 도입된 이터레이션 프로토콜은 순회가능한 데이터 컬렉션(자료구조)를 만들기 위해
ECMAScript 사양에 정의하여 미리 약속한 규칙
ES6에서는 순회가능한 데이터 컬렉션을 이터레이션 프로토콜을 준수하는 이터러블로 통일해
for...of문, 스프레드 문법, 배열 구조분해할당를 사용할 수 있게 하였다.
이러한 이터레이션 프로토콜에는 이터러블 프로토콜과 이터레이터 프로토콜이 있다.
Symbol.iterator를 프로퍼티 키로 가지는 메서드를 호출해 이터레이터 프로토콜을 준수하는 이터레이터를 반환하는 규칙이다.
그리고 이터러블 프로토콜을 준수하는 객체를 이터러블이라고 한다.
// 이터러블 객체
const iterable = {
[Symbol.iterator]() {
let cur = 1;
const max = 5;
return {
// 이터레이터 객체
next() {
// 이터레이터 리절트 객체
return { value: cur++, done: cur > max + 1 };
},
};
},
};
for (let num of iterable) {
console.log(num);
}
이터러블의 Symbol.iterator 메서드 호출시, 이터레이터를 반환한다.
이터레이터는 next 메서드를 소유하며 next 메서드를 호출시 이터러블을 순회하면서 value, done을 프로퍼티로 갖는 이터레이터 리절트 객체를 반환한다.
이러한 규칙을 이터레이터 프로토콜이라고 한다.
이터레이터는 이터러블의 요소들을 탐색하는 포인터 역할을 한다.

이터러블 프로토콜을 준수한 객체를 이터러블이라고 하였다.
이터러블은 Symbol.iterator를 프로퍼티 키로 가지는 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속받아 사용한다.
function isIterable(obj) {
return obj != null && typeof obj[Symbol.iterator] === "function";
}
// 배열, 문자열, Map등은 이터러블
console.log(isIterable([1, 2, 3])); // true (배열은 이터러블)
console.log(isIterable("안녕!")); // true (문자열은 이터러블)
console.log(isIterable(new Map())); // true (Map은 이터러블)
console.log(isIterable({})); // false (일반 객체는 이터러블이 아님)
console.log(isIterable(null)); // false (null은 이터러블이 아님)
console.log(isIterable(undefined)); // false (undefined도 이터러블이 아님)
이터러블은 for...of문 , 스프레드 문법, 배열 구조분해 할당을 사용할 수 있다.
단 Symbol.iterator가 없는 것들은 이터러블 프로토콜을 준수하는 이터러블이 아니기 때문에
for...of문 , 스프레드 문법, 배열 구조분해 할당을 사용할 수 없다.
그러나 2021년부터 TC39 프로세스의 stage 4 단계에 제안되어 있는 스프레드 프로퍼티 제안을 통해 일반객체에는 스프레드 문법을 사용할 수 있게 되었다.
TC39 Stage 4 제안이란?
TC39 프로세스의 Stage 4는 최종 승인 단계로, 해당 기능이 사양에 완전히 포함되어 표준으로 확정된 상태
스프레드 프로퍼티(Spread Properties)
스프레드 프로퍼티는 객체 리터럴의 확장 기능으로, 다음과 같은 동작을 제공한다.
객체의 프로퍼티 복사:
객체 리터럴에서 ... 문법을 사용하여 기존 객체의 프로퍼티를 복사
객체 병합 및 확장:
기존 객체를 기반으로 새로운 객체를 쉽게 만들 수 있다.
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 }; // 병합
console.log(obj2); // { a: 1, b: 2, c: 3 }
이터러블의 Symbol.iterator를 호출하면 이터레이터 프로토콜을 준수하는 이터레이터를 반환한다.
이터레이터는 next 메서드를 갖는다.
next 메서드는 이터러블의 각 요소를 순회하기위한 포인터 역할을 한다.
next 메서드를 호출하면 이터러블을 한 단계씩 순회하면서 순회결과를 나타내는 이터레이터 리절트 객체를 반환한다.
// 이터러블
const arr = [1, 2, 3];
// 이터레이터
const iterator = arr[Symbol.iterator]();
// 이터레이터의 next 메서드 호출해 이터레이터 리절트 객체 반환
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: true }
이터레이터 리절트 객체
자바스크립트는 이터레이션 프로토콜을 준수하는 객체인 빌트인 이터러블을 제공한다.
빌트인 이터러블에는 Map,Set,Array,String,arguments,DOM 컬렉션(NodeList,HTMLCollection), TypedArray가 있다.
💻 TypedArray란?
TypedArray는 고정된 크기의 이진 데이터를 다룰 수 있는 배열
보통 배열은 일반적인 자바스크립트 값들(예: 숫자, 문자열 등)을 다루지만,
TypedArray는 원시 이진 데이터(바이트)를 효율적으로 다룰 수 있다.
ex)
Int8Array: 8비트 정수
Uint8Array: 부호 없는 8비트 정수
Int16Array: 16비트 정수
const float32Array = new Float32Array(3);
// 값 할당
float32Array[0] = 1.1;
float32Array[1] = 2.2;
float32Array[2] = 3.3;
console.log(float32Array); // Float32Array(3) [ 1.1, 2.2, 3.3 ]
유사배열 객체란 객체지만 배열처럼 인덱스로 프로퍼티값에 접근할 수 있고 length 프로퍼티를 갖는 객체를 말한다.
const arrayLike = {
0: 1,
1: 2,
2: 3,
length: 3,
};
for (let i = 0; i < arrayLike.length; i++) {
console.log(i); // TypeError: arrayLike is not iterable
}
유사 배열 객체는 일반 객체이기 때문에 Symbol.iterator 메서드가 존재하지 않아
for...of문으로 순회 불가능하다.
그러나.. arguments,NodeList,HTMLCollection은 유사배열 객체이면서 동시에 이터러블 객체이다.
이 말은 순회 또한 가능하다는 의미이다.
ES6에 도입된 Array.from 메서드는 유사배열 객체나 이터러블을 배열로 변환해준다.
배열로 변환하면 순회 가능할 뿐만아니라 배열의 메서드도 이용할 수 있다.
const arrayLike = {
0: 1,
1: 2,
2: 3,
length: 3,
};
const arr = Array.from(arrayLike);
console.log(arr); // [ 1, 2, 3 ]
🛠️ Array.from()의 두 번째 인자: 맵핑 함수
Array.from()은 두 번째 인자로 맵핑 함수를 받을 수 있다!
이 함수의 인자에는 변환된 배열의 각 요소들이 호출된다.
맵핑 함수 사용하기
const arrayLike = {
0: 1,
1: 2,
2: 3,
length: 3,
};
const doubled = Array.from(arrayLike, (num) => num * 2); // 각 요소를 두 배로 변경
console.log(doubled); // [2, 4, 6]
이터러블 : Map,Set, Array, String...
이터러블은 for...of, 스프레드 문법, 배열 구조분해 할당같은 데이터 소비자에 의해 사용되므로
데이터 공급자의 역할을 한다고 할 수 있다.
만약 각각의 데이터 공급자(이터러블)들이 각자만의 순회방식을 가지면 데이터 소비자는
다양한 데이터 공급자의 순회방식을 모두 지원해야 할 것이다.
이러한 비효율적인 방식을 해결하기 위해 나온것이 이터레이션 프로토콜이다.
다양한 데이터 공급자들이 이터레이션 프로토콜을 준수하면 데이터 소비자는 이터레이션 프로토콜만 지원하도록 구현하면 된다.
이러한 이터레이션 프로토콜은 데이터 소비자와 데이터 공급자를 연결하는 인터페이스 역할을 한다.

이터레이션 프로토콜을 준수하지 않는 일반 객체도 이터레이션 프로토콜을 준수하도록 구현하면
이터러블이 된다. 이를 사용자 정의 이터러블이라고 한다.
사용자 정의 이터러블은 Symbol.iterator 메서드를 구현하고, Symbol.iterator가 next 메서드를 갖는 이터레이터를 반환하면 된다.
그리고 이터레이터의 next 메서드는 done,value 프로퍼티를 가지는 이터레이터 리절트 객체를 반환하도록 한다.
즉, 이터레이션 프로토콜을 만족시키면 된다.
1부터 n까지의 숫자를 생성하는 이터러블 생성 함수
const range = (n) => {
// 이터러블
return {
[Symbol.iterator]: function () {
let i = 0;
return {
// 이터레이터
next: () => {
if (i < n) {
// 이터레이터 리절트 객체
return { value: i++, done: false }; // 값과 done 상태 반환
} else {
return { done: true }; // 순회가 끝났을 때
}
}
};
}
};
};
for (const num of range(5)) {
console.log(num); // 0 1 2 3 4
}
만약 이터레이터를 생성하려면 Symbol.iterator 메서드를 호출해야한다.
이터러블이면서 이터레이터인 객체를 생성하면 이터레이터를 생성하기 위해 Symbol.iterator 메서드를 호출하지 않아도 된다.
const range = (n) => {
let i = 0;
return {
[Symbol.iterator]() { return this; };
next: () => {
if (i < n) {
// 이터레이터 리절트 객체
return { value: i++, done: false }; // 값과 done 상태 반환
} else {
return { done: true }; // 순회가 끝났을 때
}
}
};
}
};
};
for (const num of range(5)) {
console.log(num); // 0 1 2 3 4
}
Symbol.iterator 메서드가 반환하는 this는 객체를 가리킬 것이고 이 객체는 next 메서드를 가지고 있기 때문에 이터레이터가 되는 것이다.