보통의 함수는 하나의 값만 리턴하거나 아무것도 리턴하지 않지만 제네레이터는 필요에 따라 다수의 값을 리턴(yield)한다.
반복문이나 데이터스트림을 만드는데 용이함. 제네레이터 함수를 만들기 위해서는 특별한 문법을 써줘야 하는데 바로 function 옆에 * 기호를 붙어 function* 이라고 써주는 것이다.
function* generateSequence(){
yield 1;
yield 2;
return 3;
}
요렇게 생겼음.
제네레이터 함수는 보통의 함수와는 다르게 작동한다. 제네레이터 함수가 호출되면 코드를 바로 실행시키는 대신 특별한 오브젝트를 반환하는데 이를 generator object 라고 부른다.
function* generateSequence(){
yield 1;
yield 2;
return 3;
}
// “generator 함수”가 “generator object”를 생성한다.
let generator = generatorSequence();
alert(generator); // [object Generator]
generatorSequence 함수는 아직 시작되지 않았다.
generator 함수의 주요 method는 .next() 이다. next()가 호출되면 가장 가까운 yield 코드를 실행한다. (yield가 실행되고 나면 해당 yield는 제네레이터 함수에서 누락되고 그값은 undefined가 된다.) 그런다음 함수의 실행이 중지되고 yield의 값이 반환된다. 그래서 next()의 결과는 항상 두가지 값을 가지는 오브젝트가 된다. 하나는 value 그리고 또다른 하나는 done이다.
value: yield 값
done: 만약 함수실행이 끝났다면 true 그렇지 않으면 false.
function* generateSequence(){
yield 1;
yield 2;
return 3;
}
let generator = generateSequence();
let one = generator.next();
alert(JSON.stringify(one)); // {value:1, done: false}
여기까지 보면 코드가 첫번째 yield 까지만 실행되어 그 값이 반환되었고 함수는 이제 두번째 yield을 실행시킬 차례이다.
generator.next()를 한번 더 호출해보자. 그럼 코드가 다시 시작되고 두번째 yield를 실행시키는걸 볼 수 있다.
let two = generator.next();
alert(JSON.stringify(two)); // {value: 2, done: false}
그리고 세 번째 호출을 하게되면 실행된 코드가 return을 만나게 되어 이 함수의 실행이 끝나게 된다.
let three = generator.next();
alert(JSON.stringify(two))// {value: 3, done: true}
{value: 3, done: true} 를 반환하면서 함수의 실행이 끝났다. generator.next() 를 한번 더 부르는 것은 아무 의미가 없게 되어버렸다. 부른다고 해도 {done:true} 만 반환받게 될 것이다.
function* f(…) 와 function *f(…) 둘 중 어떻게 쓰는게 맞을까? 둘다 말은 된다. 그러나 제네레이터 함수는 함수 이름이 아니라 함수의 종류를 가르키는것이기 대문에 첫번째 방법으로 쓰는게 옳다.
generator로 반복문이 가능하다.
For of를 이용해 제네레이터가 반환하는 오브젝트의 value 값을 반복에 쓸 수 있다.
function* generateSequence(){
yield 1;
yield 2;
return 3;
}
let generator = generateSequence();
for(let value of generator){
alert(value) // 1, 2
}
.next().value 를 쓰는 것 보다 훨씬 깔끔해 보인다. 하지만 여기서 3을 제외한 1과 2만 반환이 된 걸 볼 수 있다. 왜냐하면 for of 를 써서 value를 출력하게될 때 done:true 에 해당하는 마지막 값은 무시해버리기 때문이다. 그래서 마지막 값까지 모두 for of 를 이용해 출력하고자 한다면 return 이 아니라 yield을 써 주어야 한다.
function* generateSequence(){
yield 1;
yield 2;
yield 3;
}
let generator = generateSequence();
for(let value of generator){
alert(value) // 1, 2, 3
}
제네레이터로 반복문 실행이 가능하기 때문에 이와 관련된 모든 기능들을(예를들면 spread syntex) 실행할 수도 있다.
function* generateSequence(){
yield 1;
yield 2;
yield 3;
}
let sequence = [0, …generatorSequence()];
alert(sequence) // 0, 1, 2, 3
위와같이 …generatorSequence() 가 반환한 제네레이터 오브젝트를 배열의 값으로 추가해서 쓸 수도 있다.
출저: https://javascript.info/generators#generators-are-iterable
'맨땅에 헤딩하기 > 개발공부' 카테고리의 다른 글
[ESLint disable] 검열을 거두어주십쇼 (0) | 2023.12.27 |
---|---|
[개발일기] Static HTML과 Implicit ARIA role (1) | 2023.10.07 |
[git] 문제의 시초를 잡는 조력자 git bisect (0) | 2023.08.13 |
[git] Rebase 정리 (0) | 2022.04.14 |
[TypeScript 타입스크립트 ] Utility Type 정리 - 1 (0) | 2022.04.04 |