호이스팅, 브라우저 렌더링 등과 같이 프론트엔드 기술면접 단골질문까진 아니지만, 부트캠프 수업에서 이터러블에 대해 자세히 다룬적이 없어서 이터러블에 대한 이해가 부족했다. 스터디원분들도 마찬가지가 아닐까 싶어서 공부도 할겸 이터러블로 주제를 선정하게 되었다.
이터러블과 이터레이션에 대해 알아보자
네이버 영어사전에 iterate를 찾아보면 반복하다라는 의미가 있다.
이터러블 프로토콜을 준수한 객체를 이터러블이라한다. 즉, 이터러블은 Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속받은 객체를 말한다.
// Symbol.iterator를 프로퍼티 키로 사용한 메서드
[Symbol.iterator]() {
// 이터레이터 객체 반환
}
예를 들어, 배열은 Array.prototype의 Symbol.iterator 메서드를 상속받는 이터러블이다. 이터러블은 for ... of 문으로 순회할 수 있으며, 스프레드 문법과 배열 디스트럭처링 할당의 대상으로 사용할 수 있다.
Symbol.iterator 메서드를 직접 구현하지 않거나 상속받지 않은 일반 객체는 이터러블 프로토콜을 준수한 이터러블이 아니다. 따라서 일반 객체는 for ... of 문으로 순회할 수 없으며 스프레드 문법과 배열 디스트럭쳐링 할당의 대상으로 사용할 수 없다.
const obj = {a: 1, b: 2};
// 일반 객체는 Symbol.iterator 메서드를 구현하거나 상속받지 않는다.
// 따라서 일반 객체는 이터러블 프로토콜을 준수한 이터러블이 아니다.
console.log(Symbol.iterator in obj); // false
// 이터러블이 아닌 일반 객체는 for ... of 문으로 순회할 수 없다.
for (const item of obj) { // → TypeError: obj is not iterable
console.log(item);
}
// 이터러블이 아닌 일반 객체는 배열 디스트럭처링 할당의 대상으로 사용할 수 없다.
const [a, b] = obj; // → TypeError: obj is not iterable
🤔 그렇다면 이터러블이 아닌 일반 객체는 스프레드 문법도 사용하지 못하겠다라는 생각이 들 수 있다. 하지만 스프레드 프로퍼티 제안(stage 4)은 일반 객체에 스프레드 문법의 사용을 허용한다고 한다.
const obj = {a: 1, b: 2};
console.log({...obj})l // {a: 1, b: 2};
그리고 일반 객체도 이터러블 프로토콜을 준수하도록 구현하면 이터러블이 된다고 한다.
이터러블의 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환한다. 이터레이터는 next 메서드를 소유하며 next 메서드를 호출하면 이터러블을 순회하며 value와 done 프로퍼티를 갖는 이터레이터 리절트 객체를 반환한다. 이러한 규약을 이터레이터 프로토콜이라 하며, 이터레이터 프로토콜을 준수한 객체를 이터레이터라 한다.