[JavaScript]
기초
- [JS] Js기초
- [JS] Js기초 변수
- [JS] Js기초 자료형
- [JS] Js기초 형변환
- [JS] Js기초 연산자
- [JS] Js기초 반복문
- [JS] Js기초 switch
- [JS] Js기초 function
- [JS] Js기초 객체
- [JS] Js기초 배열
중급
- [JS] Js중급 호이스팅(Hoisting)과 TDZ(Temporal Dead Zone)
- [JS] Js중급 생성자함수
- [JS] 객체 메소드(Object methods), 계산된 프로퍼티(Computed property)
- [JS] 심볼(Symbol)
- [JS] WeakMap WeakSet
- [JS] 숫자, 수학 method (Number, Math)
- [JS] 문자열 메소드(String methods)
- [JS] 배열 메소드(Array methods)
- [JS] 구조 분해 할당 (Destructuring assignment)
- [JS] 매개변수 리스트와 전개 문법(Rest parameters and spread syntax)
- [JS] 클로저(Closure)
- [JS] setTimeout / setInterval
- [JS] call / apply / bind
- [JS] 상속, 프로토타입(Prototype)
- [JS] 클래스(Class)
- [JS] 클로미스(Promise)
- [JS] 비동기 처리(Async/Await)
- [JS] Generator
- [JS] 메모리 릭(Memory Leak)
Generator는 함수의 실행을 중간에 멈췄다가 다시 시작할 수 있는 특별한 함수야! 🎯
1. Generator 기본
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Generator 함수 선언 (function* 사용)
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
// Generator 사용
const generator = numberGenerator();
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: undefined, done: true }
// for...of로 사용
for (const num of numberGenerator()) {
console.log(num); // 1, 2, 3
}
2. 값 전달하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function* twoWayGenerator() {
const a = yield 1; // 첫 번째 next()의 반환값, 두 번째 next()의 인자
console.log("a:", a);
const b = yield 2; // 두 번째 next()의 반환값, 세 번째 next()의 인자
console.log("b:", b);
return 3; // 마지막 next()의 반환값
}
const gen = twoWayGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next("hello")); // { value: 2, done: false }, 출력: a: hello
console.log(gen.next("world")); // { value: 3, done: true }, 출력: b: world
3. 비동기 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Promise를 yield하는 Generator
function* fetchUserGenerator() {
try {
const user = yield fetch("https://api.example.com/user");
const profile = yield fetch(`https://api.example.com/profile/${user.id}`);
return profile;
} catch (error) {
console.error("Error:", error);
}
}
// Generator 실행기
function runGenerator(generator) {
const gen = generator();
function handle(result) {
if (result.done) return Promise.resolve(result.value);
return Promise.resolve(result.value)
.then((res) => res.json())
.then((data) => handle(gen.next(data)))
.catch((error) => handle(gen.throw(error)));
}
return handle(gen.next());
}
// 사용
runGenerator(fetchUserGenerator)
.then((profile) => console.log(profile))
.catch((error) => console.error(error));
4. 이터레이터 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Collection {
constructor() {
this.items = [];
}
add(item) {
this.items.push(item);
}
*[Symbol.iterator]() {
for (const item of this.items) {
yield item;
}
}
}
const collection = new Collection();
collection.add("A");
collection.add("B");
collection.add("C");
// for...of 사용 가능
for (const item of collection) {
console.log(item); // "A", "B", "C"
}
// 전개 구문 사용 가능
console.log([...collection]); // ["A", "B", "C"]
5. 무한 시퀀스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 무한 피보나치 수열
function* fibonacci() {
let prev = 0,
curr = 1;
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
// 처음 5개의 피보나치 수
const fib = fibonacci();
for (let i = 0; i < 5; i++) {
console.log(fib.next().value); // 1, 1, 2, 3, 5
}
// 범위 생성기
function* range(start, end, step = 1) {
for (let i = start; i <= end; i += step) {
yield i;
}
}
// 범위 사용
for (const num of range(0, 10, 2)) {
console.log(num); // 0, 2, 4, 6, 8, 10
}
6. 실전 예제: 페이지네이션
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class DataSource {
constructor() {
this.data = Array.from({ length: 100 }, (_, i) => `Item ${i + 1}`);
}
*paginate(pageSize = 10) {
for (let i = 0; i < this.data.length; i += pageSize) {
yield this.data.slice(i, i + pageSize);
}
}
}
// 사용 예시
const ds = new DataSource();
const paginator = ds.paginate(10);
// 첫 번째 페이지
console.log(paginator.next().value); // ["Item 1", ..., "Item 10"]
// 두 번째 페이지
console.log(paginator.next().value); // ["Item 11", ..., "Item 20"]
// 모든 페이지 순회
for (const page of ds.paginate(10)) {
console.log("페이지:", page);
}
7. Generator 조합
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function* generateAlpha() {
yield "A";
yield "B";
yield "C";
}
function* generateNum() {
yield 1;
yield 2;
yield 3;
}
function* combined() {
yield* generateAlpha(); // 다른 Generator 위임
yield* generateNum();
}
// 사용
for (const value of combined()) {
console.log(value); // A, B, C, 1, 2, 3
}
꿀팁! 🍯
- Generator와 Promise 조합
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
async function* asyncGenerator() {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
for (const item of data) {
yield item;
}
}
// 사용
async function processData() {
for await (const item of asyncGenerator()) {
console.log(item);
}
}
- 에러 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function* errorGenerator() {
try {
yield 1;
throw new Error("Something went wrong");
yield 2; // 실행되지 않음
} catch (error) {
console.log("Error caught:", error.message);
yield "Error handled";
}
}
const gen = errorGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // 출력: Error caught: Something went wrong
// { value: 'Error handled', done: false }
이제 Generator는 마스터! 😎 복잡한 이터레이션과 비동기 처리를 우아하게 다룰 수 있을 거야!