[JS] for...of 문과 이터러블/이터레이터

toto9602·2024년 8월 8일

최근 온라인 강의를 듣던 중, JS의 for ... of 문의 동작에 대한 재미있는 내용을 배우게 되어 :)
본 포스팅을 통해 관련 내용을 복습 겸 정리해 보고자 합니다!

잘못된 내용에 대한 피드백은 언제나 감사드립니다! (_ _)

참고 자료

[인프런] 함수형 프로그래밍과 Javascript ES6+
MDN 문서 - for ... of
MDN 문서 - Iteration Protocols
왜 Object(객체)는 Iterable object가 아닌 것일까? (iterable과 iterator에 대해 알아보자!)

P.S 서두에서 언급한 강의는 참고 자료 제일 위에 적어 둔 <함수형 프로그래밍과 Javascript ES6+>입니다!
본 포스팅의 주요 내용 역시, 해당 강의 내용에 기반을 두고 있음을 밝힙니다 :)

1. for ... of문 살펴 보기

예시 코드

const arr = [1, 2, 3, 4, 5];

for (const element of arr) {
	console.log(element);
}

[ 출력 ]

1
2
3
4
5

설명

[ 출처 : MDN Docs ]
The for...of statement executes a loop that
operates on a sequence of values sourced from an iterable object.
Iterable objects include instances of built-ins such as Array, String, TypedArray, Map, Set, NodeList...

  1. for ... of 문은 Iterable Object에 포함된 일련의 값들에 대해 동작하는 루프를 실행!
  2. Iterable ObjectArray , String , Map , Set 등 built-in된 인스턴스들을 포함합니다!

2. 그럼...Iterable Object란 ?

[ Iterable Object ]

  • Iterable Object란, Iteration Protocol 이라는 특정한 프로토콜(규약)을 따르는 객체를 말합니다!

  • 그리고 이 Iteration Protocol은,
    다시 Iterable ProtocolIterator Protocol로 나뉩니다!

Iterable Protocol

설명

[ 출처 : MDN Docs ]
The iterable protocol allows JavaScript objects to define or customize their iteration behavior...

In order to be iterable, an object must implement the [Symbol.iterator]() method, meaning that the object (or one of the objects up its prototype chain) must have a property with a [Symbol.iterator] key which is available via constant Symbol.iterator...

[Symbol.iterator]
A zero-argument function that returns an object, conforming to the iterator protocol.

  1. Iterable Protocol은 자바스크립트 객체의 순회 동작, 그리고 순회 동작의 커스터마이징을 가능케 한다!

  2. Iterable이 되기 위해, 객체는 [Symbol.iterator] 메서드를 구현해야 한다!

  3. 여기서 [Symbol.iterator] 메서드는,
    Iterator Protocol을 따르는 객체를 반환해야 한다.

Iterator Protocol

설명

[ 출처 : MDN Docs ]
The iterator protocol defines a standard way to produce a sequence of values (either finite or infinite), and potentially a return value when all values have been generated.

An object is an iterator when it implements a next() method...

  1. Iterator Protocol은 일련의 값을 제공하는 하나의 표준 방식과,
    경우에 따라 모든 순회를 마친 이후에 반환값을 주기도 함!
  2. 특정한 조건을 갖춘 next() 메서드를 구현해야 함!

Iterator Protocol의 next() 메서드

[ 출처 : MDN Docs ]
A function that accepts zero or one argument and returns an object conforming to the IteratorResult interface.

  1. 0 ~ 1개의 argument를 받아, IteratorResult 인터페이스에 맞는 객체를 반환해야 합니다!

IteratorResult의 properties

  • done : Iterator의 순회가 종료되었는지 여부를 나타내는 boolean
  • value : Iterator가 반환한 값으로, done이 true일 때는 생략할 수 있습니다.

next() 메서드 사용 예시

// built-in Iterable인 Set을 초기화합니다. 
const setA = new Set([1,2,3]);

// Symbol.iterator 메서드를 호출하여, Iterator 객체를 얻습니다!
const iter = setA[Symbol.iterator]();

iter.next();
iter.next();
iter.next();
iter.next();

[ 출력 ]

{ value : 1, done : false }
{ value : 2, done : false }
{ value : 3, done : false }
{ value : undefined, done : true }

3. 다시 for...of

지금까지 for...of 문을 사용할 수 있는 Iterable 객체와, Iterable 객체가 따르는 Iteration Protocol에 대해 간단히 살펴 보았습니다!

for...of 문은 Iterable 객체에 대해 사용이 가능!
→ Iterable / Iterator 프로토콜을 따라, Iterable 객체의 개별 값들을 순회!

cf 1. [Symbol.iterator] 메서드가 없으면 ?

const arr = [1,2,3];

// [Symbol.iterator] 메서드를 임의로 삭제
arr[Symbol.iterator] = null;

for (const a of arr) {
  console.log(a)
}

[ 출력 ]

TypeError : arr is not iterable

for...of 문은 Iterable / Iterator 프로토콜을 따라 동작하기 때문에, 해당 프로토콜의 [Symbol.iterator] 메서드를 임의로 지워주면 TypeError가 발생합니다! :)

cf 2. 전개 연산자 (spread syntax)

자바스크립트의 전개 연산자(...)도 역시 Iterable / Iterator 프로토콜을 따릅니다!

const arr = [1,2];

// 역시 임의로 [Symbol.iterator] 메서드를 삭제
arr[Symbol.iterator] = null;

console.log([...arr]);

[ 출력 ]

TypeError : arr is not iterable

그래서, [Symbol.iterator] 메서드를 임의로 지워주면 역시 동일한 에러가 발생하네요! :)

정리

  • 자바스크립트의 for...of 문은 Iterable Object에 대해 사용할 수 있다!

  • Iterable Object란 Iteration Protocol을 따르고 있는 객체를 말하며,
    Iteration Protocol의 종류는 Iterable ProtocolIterator Protocol로 구분된다 :)

    • Iterable : Iterator를 반환하는 [Symbol.iterator] 메서드를 구현!
    • Iterator : 순회 대상인 value 와, 순회 종료 여부를 나타내는 done 을 반환하는 메서드인 next() 를 구현!
profile
주니어 백엔드 개발자입니다! 조용한 시간에 읽고 쓰는 것을 좋아합니다 :)

0개의 댓글