34. 이터러블

2023. 1. 19. 21:37기록/Modern JavaScript Deep Dive

이터레이션 프로토콜

순회 가능한 데이터 컬렉션을 만들기 위해
ECMAScript 사양에 정의하여 미리 약속한 규칙

 

1. 이터러블

이터러블 프로토콜을 준수한 객체
Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나
프로토타입 체인을 통해 상속받은 객체
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({}); // true

 

배열은 Array.prototype의 Symbol.iterator 메서드를 상속받는 이터러블임

for ... of 문으로 순회 가능 / 스프레드 문법과 배열 디스트럭처링 할당의 대상으로 사용 가능

const array = [1, 2, 3];

// 배열은 Array.prototype의 Symbol.iterator 메서드를 상속받는 이터러블임
console.log(Symbol.iterator in array); // true

// 이터러블인 배열은 for ... of 문으로 순회 가능
for (const item of array) {
  console.log(item);
}

// 이터러블인 배열은 스프레드 문법의 대상으로 사용 가능
console.log([...array]); // [1, 2, 3]

 

2. 이터레이터

이터러블의 Symbol.iterator 메서드를 호출하면 이터레이터를 반환함
반환된 이터레이터는 next 메서드를 가짐

next 메서드를 호출하면 이터러블을 순차적으로 순회하며 순회 결과를 나타내는

이터레이터 리절트 객체를 반환함

 

이터레이터 리절트 객체의 value 프로퍼티는 현재 순회 중인 이터러블의 값을 나타내며

done 프로퍼티는 이터러블의 순회 완료 여부를 나타냄

// 배열은 이터러블 프로토콜을 준수한 이터러블임
const array = [1, 2, 3];

// Symbol.iterator 메서드는 이터레이터를 반환함
const iterator = array[Symbol.iterator]();

// Symbol.iterator 메서드가 반환한 이터레이터는 next 메서드를 가짐
console.log('next' in iterator); // true

// 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 }

빌트인 이터러블

빌트인 이터러블 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[Symbol.iterator]
DOM 컬렉션 NodeList.prototype[Symbol.iterator]
HTMLCollection.prototype[Symbol.iterator]

for ... of 문

for (변수선언문 of 이터러블) { ... }

내부적으로 이터레이터의 next 메서드를 호출하여 이러터블을 순회하며

next 메서드가 반환한 이터레이터 리절트 객체의 value 프로퍼티 값을 for ... of 문의 변수에 할당함

이터레이터 리절트 객체의 done 프로퍼티 값이 false이면 이터러블의 순회를 계속하고

true이면 이터러블의 순회를 중단함

 

for ... in 문

for (변수선언문 in 객체) { ... }

은 객체의 프로토타입 체인 상에 존재하는 모든 프로토타입의 프로퍼티 중에서

프로퍼티 어트리뷰트 [[Enumerable]]의 값이 true인 프로퍼티를 순회하며 열거함

이때 프로퍼티 키가 심벌인 프로퍼티는 열거하지 않음


이터러블과 유사 배열 객체

유사 배열 객체는 이터러블이 아닌 일반 객체임

Symbol.iterator 메서드가 없기 때문에 for ... of 문으로 순회 불가능

 

단, arguments, NodeList, HTMLCollection 은 유사 배열 객체이면서 이터러블임

Array.from 메서드를 사용하여 유사 배열 객체 또는 이터러블을 인수로 전달하여 배열로 변환 가능


이터레이션 프로토콜의 필요성

이터레이션 프로토콜은 다양한 데이터 공급자가 하나의 순회 방식을 갖도록 규정하여

데이터 소비자가 효율적으로 다양한 데이터 공급자를 사용할 수 있도록

데이터 소비자와 데이터 공급자를 연결하는 인터페이스의 역할을 함

 

데이터 소비자

for ... of

스프레드 문법

배열 디스트럭처링 할당

Map/Set 생성자

 

데이터 공급자

Array

String

Map/Set

DOM 컬렉션