[Generator 함수를 이해해보자 (이론편).2/3, Yield] 3. 제네레이터 함수의 "정의,What"와 "작동원리,How"는 무엇인가?(이어서)

calm·2019년 3월 2일
2
post-thumbnail

[해당 이미지는 다음 링크에서 사용했습니다 : http://welllin.net/javascript-es6-generator/]

#제네레이터 함수 #제네레이터 함수는 무엇인가 #yield란 #제네레이터함수 작동 #yield 표현식

여기서 잠깐!

이 블로그는 제네레이터 함수 공부하며 참고한 블로그 내용을 재 가공해 작성 한 글입니다.
중복되는 용어와 해당 부분에 대해 링크를 정리했습니다.궁금하신 분은 주소를 클릭하면 원문을 읽을 수 있습니다.

시작하는 글

지난 글 이론편에서 “어디에” 제네레이터 함수를 써야하는가?를 다뤘습니다.

오늘 우리는 제네레이터 함수가 무엇이고 어떻게 동작하는지에 대해 하나씩 살펴볼 것 입니다.

구성

블로그를 이론적인 부분과 코드편으로 나눠 작성됩니다. 현재 이론편을 다루고 있습니다.

(각각의 모든 글 하단에 참고&인용한 블로그 링크를 추가했습니다.)

목 차

[1]. “왜” 제네레이터 함수를 써야 하는가?
[2]. “어디에” 제네레이터 함수를 써야하는가?
[3]. 제네레이터 함수의 "정의"와 "작동원리"는 무엇인가?

세부 목차

[3] 제네레이터 함수의 "정의"와 "작동원리"는 무엇인가

[이전 글에서]
1. 제네레이터 함수란 무엇인가?

  • 1-1. 비유와 정의
  • 1-2. 일반함수와 제네레이터 함수의 차이점
  • 1-2-1. Run-to-completion과 coroutine(코루틴)
  • 1-2-2. 결괏값 : Value VS 이터레이터(Iterator)
  • 1-2-3. 값을 유지한다.
  • 1-3. 작성 방법
  • 1-4. 함수 작동순서
  1. 제네레이터는 어떻게 작동할까?
  • 2-1. yield를 어떻게 바라볼까?
    1. 함수를 중지하거나 재개시키는 yield
    1. 값을 출력되는 경우인 yield - 1
    1. 값이 전달되는(할당하는) 경우인 yield - 2

    [이어서]

  • 2-2. yield와 next()의 관계는 무엇인가?

여기서 잠깐!

지금까지 제네레이터 함수가 어떻게 생겼고, 기본적인 코드가 어떻게 작동하는지 알아봤습니다.

지금부터는 yield를 어떻게 바라보고 해석할지 yield에 대해서 다루려고 합니다.

동시에 yield를 다루는 next()메서드에 대해서 이야기합니다.
yield는 next()호출을 통해 값을 "넘겨주는데" 항상 yield와 next()가 1:1로 (숫자가) 매칭이 안 될 수도 있습니다.
그 이유에 대해서 알아봅시다.

2-1. yield를 어떻게 바라볼까?

1. 함수를 중지하거나 재개시키는 yield

MDN을 보면 yield를 다음과 같이 말하고 있습니다.

yield 키워드는 제너레이터 함수 (function* 또는 레거시 generator 함수)를 중지하거나 재개하는데 사용됩니다.

다음 그림은 일반함수와 비교해 yield가 제네레이트 함수에서 어떻게 작동하는지 설명합니다.

returns a generator object(iterator)

제네레이터 함수는 함수가 시작하면서 이터레이터 객체를 반환합니다.

Generators starts either by manually calling next( ) or using in loops/functions

제네레이터 함수는 next( )메서드로 시작합니다. 이때 만약 for문과 같은 loop나 작성된 함수function에 들어가서 제네레이터 함수가 실행됩니다.

encounters yield
Yield the value, Pause(save state) and exit

값(value)를 반환하고 멈춥니다. 그리고 제네레이트 함수가 종료합니다.
이때 상태(값)을 저장할 수 있는데, 호출하는 메서드 next( )메서드에 인자가 있을 경우 넣을 수 있습니다.
예) next(a)

Resume

중요한 부분입니다.
이전 yield에서 종료가 됐기 때문에, 종료된 바로 그 지점에서 다시 시작 됩니다.

Yield the value, Pause(save state) and exit

값(value)를 반환하고 멈춥니다. 그리고 제네레이트 함수가 종료합니다.
이때 상태(값)을 저장할 수 있는데, 호출하는 메서드 next( )메서드에 인자가 있을 경우 넣을 수 있습니다.
예) next(a)
이와 같은 루프를 계속 돌게 됩니다.

일반함수에서는 return이 있지만 제네레이터함수에서는 발견할 수가 없습니다. 대신 yield 키워드가 있습니다

2. 값을 출력되는 경우인 yield- 1

"출력한다" 라는 말은 값으로서 console.log()에서나 반환된 결괏값 상태일 때를 의미합니다.

yield는 2가지 역할을 한다고 생각합니다.
첫째, 값을 출력하는 yield
둘째, 값을 전달하는 yield

yield는 다음과 같이 작성됩니다.

[returnValue] = yield [expression ]

제네레이터 함수는 yield 키워드를 만나면 [expression] 부분을 넘기고(yield) 잠시 종료됩니다.
[expression]은 선택적으로 작성되며 없을 경우 undefined를 반환합니다.

[expression]의 값이 제네레이터 객체가 반환하는 객체 중 value에 해당합니다.

{value:[expression], done:true|false}

예를 들어 다음의 표현식이 있다고 가정합니다.

let a = yield 20
let b = yield c+d

제네레이터 함수는 yield를 만나면서 "20"을 넘기고 실행을 종료합니다.
다시 함수가 실행되면서 "c+d"를 넘기고 종료합니다.

다음과 같이 결과값을 반환합니다.

{value:20, done:false}
{value:c+d, done:false}

아직 이터레이터 객체 안에 출력할 값이 있는지 없는지 모르기 때문에 done 프로퍼티는 false라고 가정했습니다.

3. 값이 전달되는(할당하는) 경우인 yield - 2

yield의 특성은 아니지만, yield를 둘러싼 주변 환경의 모습을 설명하는 것이다.

[returnValue] = yield [expression ]

대입 연산자 "=" 를 만나면, 값을 할당하게 됩니다.
하지만 yield에서는 값을 바로 왼쪽 [returnValue]에 할당하지 않습니다.
값이 대입 될 경우에는 이터레이터 객체가 호출하는 next()에 파라메타가 있는 경우다.

즉. 다음의 경우에만 [returnValue]에 yield의 표현식 결괏값이
할당됩니다.

function * generator_function(){
let a = yield 20
}

const generator_function = generator_function();
generator_function.next(10);
console.log(a)

next()메서드의 파라메타 값이 yield 왼쪽 [returnValue]에 들어갑니다.

다음의 코드로 yield의 1,2내용을 정리해 봅시다.

function* generator() {
  let a = yield 10; // yield #1
  let b = a + 20;  // yield #2
  return b;
}

const generatorFunction = generator();

console.log(generatorFunction.next().value); // next #1;
console.log(generatorFunction.next(10).value); // next #2

과정은 이렇습니다.

console.log(generatorFunction.next().value); // yield #1;

첫번째 yield 10 에 해당하는 첫번째 next() 입니다.

console.log(generatorFunction.next(10).value); // next #2

두번째 yield a+20 에 해당하는 두번째 next(10) 입니다.
첫번째 next()메서드와 다른 점은 인자 "10"이 있다는 점입니다.

위에서 언급한대로,
yield 왼쪽에 있는 변수, [returnValue]는 next()메서드의 파라미터 값이 들어갑니다.
그러므로 a의 값은 10이 됩니다.
그래서 b는 a+20, 즉, 20 + 10이 되어 30이 됩니다.

다음 편에는 제네레이터 함수의 정의와 작동원리를 계속 이어 설명하겠습니다.

참고&인용 레퍼런스 링크

yield(MDN) : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/yield
yield,제네레이트 함수에서 작동하는 그림 : https://codeburst.io/understanding-generators-in-es6-javascript-with-examples-6728834016d5
값이 전달되는(할당하는) 경우인 yield: ECMASCRIPT 6, 제네레이터, 루비페이퍼

profile
공부한 내용을 기록합니다

0개의 댓글