Symbol, 이터러블 프로토콜, for...of, 제너레이터 function* 를 다룬다.
이터레이터·제너레이터·심볼
for...of 가 어떻게 배열을 순회하는지 궁금했다면, 그 비밀은 이터레이터에 있습니다. 이번 레슨에서는 Symbol, 이터러블 프로토콜, 제너레이터까지 언어의 깊은 곳을 들여다봅니다.
학습 목표
Symbol의 용도와 특성을 이해한다- 이터러블 프로토콜의 동작을 설명할 수 있다
for...of로 다양한 자료구조를 순회할 수 있다- 제너레이터
function*와yield를 사용할 수 있다 - 제너레이터를 실무에 활용할 수 있다
Symbol
Symbol 은 유일무이한 값을 만드는 원시 타입입니다. 같은 설명을 주어도 절대 같지 않습니다.
const a = Symbol('id');
const b = Symbol('id');
console.log(a === b); // → false (항상 고유)
// 객체 키로 쓰면 충돌·중복이 없는 "숨은" 속성이 됨
const ID = Symbol('id');
const user = { name: '민수', [ID]: 1001 };
console.log(user[ID]); // → 1001
💡 TIP — Symbol 키는 일반 순회(
for...in,Object.keys)에 나타나지 않아 메타데이터를 숨기는 데 쓰입니다. 또Symbol.iterator같은 "잘 알려진 심볼"이 언어 동작을 정의합니다.
이터러블 프로토콜
객체가 Symbol.iterator 메서드를 가지면 이터러블이 되어 for...of·스프레드·구조 분해의 대상이 됩니다. 그 메서드는 next() 를 가진 이터레이터를 돌려줍니다.
const range = {
from: 1,
to: 3,
[Symbol.iterator]() {
let current = this.from;
const last = this.to;
return {
next() {
return current <= last
? { value: current++, done: false }
: { value: undefined, done: true };
},
};
},
};
console.log([...range]); // → [1, 2, 3]
for (const n of range) console.log(n); // → 1, 2, 3
next() 는 { value, done } 형태를 돌려주며, done: true 가 되면 순회가 끝납니다.
for...of
이터러블이라면 무엇이든 for...of 로 순회합니다.
for (const ch of '가나다') console.log(ch); // → 가, 나, 다
for (const x of new Set([1, 2, 2])) console.log(x); // → 1, 2
for (const [k, v] of new Map([['a', 1]])) console.log(k, v); // → a 1
⚠️ 주의 — 일반 객체(
{})는 이터러블이 아니라for...of로 돌 수 없습니다. 키-값 순회는Object.entries(obj)로 이터러블을 얻으세요.
제너레이터 — function*
제너레이터는 이터레이터를 간단히 만드는 함수입니다. function* 로 선언하고 yield 로 값을 하나씩 내보냅니다.
function* count() {
yield 1;
yield 2;
yield 3;
}
const gen = count();
console.log(gen.next()); // → { value: 1, done: false }
console.log(gen.next()); // → { value: 2, done: false }
console.log([...count()]); // → [1, 2, 3]
함수는 yield 에서 멈췄다가 다음 next() 호출 때 이어서 실행됩니다.
function* range(from, to) {
for (let i = from; i <= to; i++) {
yield i;
}
}
console.log([...range(1, 5)]); // → [1, 2, 3, 4, 5]
앞의 range 객체를 제너레이터로 다시 쓰면 훨씬 짧아집니다.
const iterable = {
from: 1,
to: 3,
*[Symbol.iterator]() {
for (let i = this.from; i <= this.to; i++) yield i;
},
};
console.log([...iterable]); // → [1, 2, 3]
활용 — 무한 시퀀스와 ID 생성기
제너레이터는 필요할 때마다 값을 계산하므로 무한 수열도 다룰 수 있습니다.
function* idMaker() {
let id = 1;
while (true) {
yield id++;
}
}
const next = idMaker();
console.log(next.next().value); // → 1
console.log(next.next().value); // → 2
💡 TIP — 제너레이터는 메모리에 모든 값을 담지 않고 요청 시점에 하나씩 만들어내므로(지연 평가), 큰 데이터나 무한 시퀀스에 적합합니다.
요약
Symbol은 고유한 값으로, 충돌 없는 객체 키와 언어 동작 정의에 쓰인다Symbol.iterator메서드를 가지면 이터러블이 되어for...of·스프레드가 가능하다- 이터레이터의
next()는{ value, done }을 돌려준다 - 제너레이터
function*와yield로 이터레이터를 간단히 만든다 - 제너레이터는 지연 평가로 무한 시퀀스와 큰 데이터를 효율적으로 다룬다
연습문제
Symbol두 개를 만들고 같은 설명이어도 다르다는 것을 비교로 확인하세요.- 1부터 n까지 짝수만 내보내는 제너레이터
evens(n)을 작성하세요.힌트 —
for안에서if (i % 2 === 0) yield i; - 객체에
[Symbol.iterator]를 구현해for...of로 순회 가능하게 만드세요. - 호출할 때마다 1씩 증가하는 ID 를 돌려주는 무한 제너레이터를 작성하고 3번 호출해 보세요.
힌트 —
while (true) yield id++;
💡 연습문제 풀이
불러오는 중…
댓글 0
“JavaScript” 강좌에 대한 댓글입니다.