* Generator : 함수의 실행을 중간에 멈췄다가 재개할 수 있는 기능
ex) Redux Saga
> * 을 사용해서 만든다.
> 내부에 yield를 사용한다.
> yield에서 함수의 실행을 멈출수있다.
> next(), return(), throw() 메소드를 가진다.
* Generator
> iterable (반복이 가능한)
- Symbol.iterator 메서드가 있다.
- Symbol.iterator는 iterator를 반환해야한다.
- for ... of 를 통해서 순회 가능하다.
> iterator (반복자)
- next 메서드를 가진다.
- next 메서드는 value와 done속성을 가진 객체를 반환한다.
- 작업이 끝나면 done는 true가 된다.
function* fn() {
yield 1;
yield 2;
yield 3;
return "finish";
}
const a = fn();
// next()를 사용하면 가장가까운 yield를 만날때까지 코드를 실행시키고 데이터 객체를 반환해준다.
// yield를 만나면 멈춘다.
// value는 yield옆에 있는 값이다. 생략하면 undefined가 반환된다.
// done는 함수가 끝났는가 여부이며 함수가 끝나면 true가 반환된다.
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()
function* fn() {
yield 1;
yield 2;
yield 3;
return "finish";
}
const a = fn();
// return()메서드를 사용하면 그 즉시 done : true가 된다.
a.return("END") // {value: 'END', done: true}
a.next() // {value: undefined, done: true} 함수가 종료되었기때문에 undefined가 출력된다.
* throw()
function* fn() {
try {
yield 1;
yield 2;
yield 3;
return "finish";
} catch (e) {
console.log(e);
}
}
const a = fn();
a.next(); {value : 1, done : false}
a.throw(new Error('err')) // error로그가 찍히고 value : undefined, done : true가 된다.
* array가 가지고있는 iterator확인
> 배열은 Symbol.iterator메서드를 가지고 있고 이 메서드가 반환하는 값이 iterator이므로 iterable하다고 할 수 있다.
> 즉, 배열은 반복가능한 객체이다.
> for ... of를 통해서 순회 가능하다.
const arr = [1, 2, 3, 4, 5]
const it = arr[Symbol.iterator]();
it.next(); // {value : 1, done: false}
it.next(); // {value : 2, done: false}
it.next(); // {value : 3, done: false}
it.next(); // {value : 4, done: false}
it.next(); // {value : 5, done: false}
it.next(); // {value : undefined, done: true}
for (let num of arr) {
console.log(num)
};
// 1
// 2
// 3
// 4
// 5
* iterator예시 코드
function* fn() {
yield 4;
yield 5;
yield 6;
}
const a = fn();
a[Symbol.iterator]() === a; // true
// Generator의 Symbol.iterator메서드를 실행한 값이 자기자신이다. (true)
// 즉, Generator는 iterable객체이다.
// for of또한 사용가능하다.
for(let num of a){
console.log(num);
}
// 4
// 5
// 6
* 문자열 iterator
const str = 'hello';
str[Symbol.iterator]
const xx = str[Symbol.iterator]
xx.next(); { value : "h", done: false }
xx.next(); { value : "e", done: false }
xx.next(); { value : "l", done: false }
xx.next(); { value : "l", done: false }
xx.next(); { value : "o", done: false }
for(let s of xx) {
console.log(s);
}
// h
// e
// ②l
// o
* next()에 인수 전달 : 외부로부터 값을 입력 받을 수 있다.
function* fn() {
const num1 = yield "첫번째 숫자를 입력해주세요";
console.log(num1);
const num2 = yield "두번째 숫자를 입력해주세요";
console.log(num2);
return num1 + num2;
}
const a = fn();
a.next(); // {value: '첫번째 숫자를 입력해주세요', done: false}
a.next(2); // 2 {value: '두번째 숫자를 입력해주세요', done: false} // 값은 num1에 저장된다.
a.next(4); // 4 {value : 6, done: true} // value에는 num1 + num2값이 반환된다.
* Generator은 값을 미리 만들어 두지않는다. // 메모리 관리측에서 효율적이다.
> while(true)를 사용해서 무한반복을 만들어도 브라우저가 꺼지지않는다.
> next()를 줄때마다 값을 호출하기 때문이다.
> 필요한순간까지 계산을 미룰 수 있다.
function* fn() {
let index = 0;
while (true) {
yield index++;
}
}
const a = fn();
a.next(); // {value: 0, done: false}
yield*을 이용
> for of와 마찬가지고 done : true가 될때까지 값을 펼쳐준다.
> *옆에는 반복가능한 모든 객체가 옆에 올수있다.
function* gen1() {
yield "W";
yield "o";
yield "r";
yield "l";
yield "d";
}
function* gen2() {
yield "Hello,";
yield* gen1();
yield "!";
}
console.log(...gen2()); // Hello, W o r l d !
'Study > JavaScript' 카테고리의 다른 글
[JavaScript_study] DOM & EVENT 노드 생성, 추가, 복제, 삭제 (0) | 2022.03.24 |
---|---|
[JavaScript_study] DOM & EVENT 부모,자식,형제 노드 (0) | 2022.03.24 |
[JavaScript_study] 클로저 (Closure) (0) | 2022.03.23 |
[JavaScript_study] Rest parameters, Spread syntax (0) | 2022.03.23 |
[JavaScript_study] 구조 분해 할당 (Destructuring assignment) (0) | 2022.03.23 |