Generator

UYeong·2021년 8월 17일
0

Javascript

목록 보기
1/1

제너레이터 함수 사용해보기

우리가 일반적으로 사용하는 일반 함수는 하나의 값(혹은 0개의 값)만을 반환한다.

예를 들어서 다음과 같은 함수가 있다고 가정해보면

function weirdFunction() {
  return 1;
  return 2;
  return 3;
}

함수에서 값을 여러번에 걸쳐서 반환하는 것은 불가능합니다. 이 함수는 호출 할 때마다 무조건 1을 반환하게 된다.

하지만 제너레이터 함수를 사용하면 여러 개의 값을 필요에 따라 하나씩 반환(yield)할 수 있다.


제너레이터 함수 만들기

제너레이터 함수를 만들 때에는 function* 이라는 키워드를 사용한다.

function* generatorFunction() {
    yield 1;
    yield 2;
    yield 3;
}
generatorFunction(); // {<suspended>}

yield들을 함수안에 넣어 제너레이터 함수를 만든 것이다.
만든 제너레이터 함수를 호출해보면 {<suspended>} 라는 하나의 객체가 반환된다.

따라서 함수를 작성한 뒤에는

const generator = generatorFunction();

이렇게 제너레이터 함수를 generator란 변수에 저장해준뒤 변수 generator를 활용해주면 된다.



제너레이터 함수 사용1

제너레이터 함수를 이용하면 함수를 실행했을때 함수를 특정 구간에서 멈춰놓거나, 나중에 멈춘 시점에서 이어서 실행 할 수도 있다.
그리고 결과값을 순차적으로 여러번 반환할 수도 있다.

그럼 제너레이터 함수를 실행 해보면
위의 코드에서 처럼 제너레이터 함수를 호출한다고 해서 해당 함수 안의 코드가 바로 시작되지는 않다.

따라서 .next() 이용해 generator.next()로 호출해야만 코드가 실행된다.

function* generatorFunction() { 
    yield 1;
    yield 2;
    yield 3;
}

const generator = generatorFunction();
generator.next(); // {value: 1, done: false}
generator.next(); // {value: 2, done: false}
generator.next(); // {value: 3, done: false}
generator.next(); // {value: undefined, done: true} 
generator.next(); // {value: undefined, done: true} 

next()를 실행하면 1, 2번을 순서대로 수행.

  1. 아래 두 속성을 가진 객체를 반환.
  {
    value: (yield값이 있으면) yield 값, (없으면) undefined,
    done: (함수 코드 실행이 끝나지 않았으면) false, (끝났으면) true 
  }
  1. yield에 의해 코드 실행을 멈춤.

코드의 실행이 멈추고 나서 generator.next() 를 다시 호출하면 다시 이어서 1,2 번이 순차적으로 실행된다.

만약 {done: true} 가 한번이라도 나오면
generator.next()를 호출해도 아무 소용이 없다. generator.next()를 여러번 호출해도 객체 {done: true}가 반환될 뿐이다.

또한 yield대신 return을 넣어도 리턴값만 출력한뒤 done이 true가 되고 함수를 종료하기 때문에 마찬가지로 객체 {done: true} 만 반환된다.

function* generatorFunction() { 
    yield 1;
    return 2; //리턴을 넣으면 리턴값을 반환후
              //done 이 true가 되고 제너레이터 함수를 끝냄
}

const generator = generatorFunction();
generator.next(); // {value: 1, done: false}
generator.next(); // {value: 2, done: true}
generator.next(); // {value: undefined, done: true}



제너레이터 함수 사용2

제너레이터 함수는 next 를 호출 할 때 인자를 전달하여 이를 제너레이터 함수 내부에서 사용 할 수 있다.

function* sumGenerator() {
    console.log('더하기를 해보겠습니다.')
    let a = yield;
    console.log('a는 1');
    let b = yield;
    console.log('b는 2');
    let c = yield;
    console.log('c는 3 답은?');
    yield a + b + c; 
}

const sum = sumGenerator();
sum.next(); //더하기를 해보겠습니다. , {value: undefined, done: false}
sum.next(1); //a는 1 , {value: undefined, done: false}
sum.next(2); //b는 2 , {value: undefined, done: false}
sum.next(3); //c는 3 답은? , {value: 6, done: false}

마지막으로 sum.next(3); 했을때 yield a + b + c; 에 의해 value의 속성값에 yield값이 넣어져 나온다.



제너레이터 함수 사용3

위에서 next()를 활용하는 것을 보면 generator는 이터러블(반복이 가능한) 객체인걸 알 수 있다.
따라서 for..of 반복문을 사용해 값을 얻을 수 있다.

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

let generator = generateSequence();

for(let value of generator) {
  alert(value); // 1, 2
}

여기서 출력된 값들을 보면 1과 2만 출력되고 3은 출력되지 않는 걸 알 수 있다.

이유는 for..of 반복문이 done: true일 때는 value를 무시하기 때문이다. 그러므로 for..of를 사용했을 때 모든 값이 출력되길 원한다면 yield로 바꿔 값을 반환해야 한다.

function* generateSequence() {
  yield 1;
  yield 2;
  yield 3;
}

let generator = generateSequence();

for(let value of generator) {
  alert(value); // 1, 2, 3
}

1,2,3 이 모두 출력되었다.


추가

제너레이터가 이터러블 객체라면 제너레이터에도 전개 문법(...) 같은 관련 기능도 사용할 수 있다.

function* generateSequence() {
  yield 1;
  yield 2;
  yield 3;
}

let sequence = [0, ...generateSequence()];

alert(sequence); // 0, 1, 2, 3

위 예시에서 ...generateSequence()에 의해 호출되는 제너레이터 객체들의 value값들을 배열의 요소로 바꿔준다.





참고
profile
Create the brilliant service for the world

0개의 댓글