JavaScript 19장 - 개념짚기 (13)
포스트
취소

JavaScript 19장 - 개념짚기 (13)

JavaScript

Generator

  • 함수에 실행을 중간에 멈췄다가 재개할 수 있는 독특한 기능을 한다.
  • function옆에 *을 써서 만들고 함수 내부에 yield 키워드를 사용한다.
  • yield키워드로 함수를 멈출 수 있다.
  • next 키워드로 사용되고, next를 사용하기 전까지 함수 내부의 코드는 실행되지 않는다.
  • next를 사용 시, 가장 가까운 yield문을 만날 때까지 실행되고 데이터 객체를 반환한다.
  • 반환 된 객체는 valuedone 프로퍼티를 가지는데, valueyield에 오른쪽에 작성된 값이다.
  • done은 함수가 끝났는 지를 나타내며, 함수가 끝났으면 true, 끝나지 않았으면 false로 나타낸다.
  • next를 사용하여 다른 작업을 하다가 다시 돌아와서, 멈춰있던 부분부터 이어서 실행하게 된다는 장점이 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function* f1() {
  yield 1;
  yield 2;
  yield 3;
  return "finish";
}

const a = fn();
a; // f1{<suspended>}
a.next(); // {value: 1, done: false}
a.next(); // {value: 2, done: false}
a.next(); // {value: 3, done: false}
a.next(); // {value: "finish", done: true}
a.next(); // {value: undefined, done: true}

return()

  • return()을 사용하여 즉시 함수를 종료할 수 있다.
1
2
3
4
5
6
7
8
9
10
function* f1() {
  yield 1;
  yield 2;
  yield 3;
  return "finish";
}

const a = fn();

a.return("End"); // {value: "End", done: true}

throw()

  • throw()를 통해 try...catch문을 실행할 수 있다.
  • 마찬가지로 즉시 함수를 종료한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function* f1() {
  try {
    yield 1;
    yield 2;
    yield 3;
    return "finish";
  } catch (e) {
    return e;
  }
}

const a = fn();

a.throw(new Error("err")); // {value: "Error: err...", done: true}

iterable, iterator

  • iterator란 반복 가능한 객체를 순회하는 데 사용되는 객체이다.
  • 배열의 prototype에는 Symbol.iterator메서드가 있는데 iteratornext메서드는 valuedone속성을 가진 객체를 반환한다.
  • 배열에서 for...of와 마찬가지로 Generator 또한 순회하며 반복하기 때문에, 구조분해 할당 시 donetrue가 될 때까지 값을 펼쳐주는 역할을 한다.
1
2
3
4
5
// 반복 가능한 객체이다.
// 문자열도 iterable이다.
const arr = [1, 2, 3, 4, 5];

arr[Symbol.iterator](); // Array Iterator {}

외부 인자

  • next안에 입력한 값은 yield에 할당된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function* f1() {
  const num1 = yield "첫 번째 숫자";
  console.log(num1);

  const num2 = yield "두 번째 숫자";
  console.log(num2);

  return num1 + num2;
}

const a = f1();

a.next(1);
// {value: "첫 번째 숫자", done: false}
// 1 (next(1)이 할당됨)
a.next(15);
// {value: "두 번째 숫자", done: false}
// 15

a.next(); // {value: 16, done: true}
  • Generator는 외부로부터 값을 전달받을 수 있기 때문에, 값을 미리 만들어두지 않는다.
  • 필요한 순간에만 사용되기 때문에 메모리 측면에서 효율적이다.
  • 예시로, break가 없는 while문을 사용하더라도 필요한 순간에만 사용되기 때문에 사실상 무한 반복되지 않는다.
1
2
3
4
5
6
7
8
9
10
11
12
function* f1() {
  let index = 0;
  while (true) {
    yield index++;
  }
}

const a = f1();
a.next(); // {value: 1, done: false}
a.next(); // {value: 2, done: false}
a.next(); // {value: 3, done: false}
a.next(); // {value: 4, done: false}

yield*

  • yield을 사용하여 다른 Generator를 참조할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
function* f1() {
  yield "H";
  yield "i";
}

function* f2() {
  yield "Say";
  yield* f1();
  yield* "!";
}

console.log(...f2()); // Say H i !
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.