This is the 12th day of my participation in Gwen Challenge
A Generator, also known as a Generator function, is essentially a function, but it can return multiple times. Generator is a new data type introduced by the ES6 standard.
concept
A generator is an ordinary function characterized by:
- There is an asterisk (*) between the function keyword and the function name,
function*
- Inside the function body, yield expressions are used to define different internal states (yield means “output” in English).
- The function body uses a return inside, which returns the given value and terminates traversing the Generator function.
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
yield x + 4;
}
Copy the code
Generator functions compared to normal functions:
- Both are executed through parentheses ().
- When a generator function is called, the function is not executed immediately, and instead of returning the result of the function’s execution, an iterator object is returned.
- Through the iterator object
next
Method executes the function piecewise to get the inside of the functionyield
The output value.
const r = foo(0);
r.next();
// { value: 1, done: false }
r.next();
// { value: 2, done: false }
r.next();
// { value: 3, done: true }
r.next();
// {value: undefined, done: true} is returned
r.next();
// { value: undefined, done: true }
Copy the code
Yield expression
Yield can only be used in generator functions, and using it in normal functions or elsewhere yields a syntax error. Yield represents the pause flag inside the generator and the output value for the place where the call was made.
Yield expressions have similarities and differences with return statements.
- The similarity is that you can return the value of the expression immediately following the statement.
- The difference is in each encounter
yield
, the function suspends execution and continues backward from that position the next time, whilereturn
Statements do not have the function of location memory. - A function can only be executed once (or once)
return
Statement, but can be executed multiple times (or more)yield
Expression. - A normal function can only return one value because it can only be executed once
return
;Generator
Functions can return a series of values, because there can be as many as you wantyield
.
Next method
The yield expression itself returns no value, or always returns undefined. The next method can take an argument that is treated as the return value of the previous yield expression.
The context state of a Generator function does not change from its paused state to its resumed state. With the parameters of the next method, there is a way to continue injecting values into the function body after the Generator function has started running. That is, the behavior of the Generator function can be adjusted by injecting different values from outside to inside at different stages of its operation.
function* dataConsumer () {
console.log('Started');
console.log(` 1.The ${yield}`);
console.log(` 2.The ${yield}`);
return 'result';
}
// Equivalent code
function* dataConsumer () {
console.log('Started');
let result = yield;
console.log(` 1.${result}`);
result = yield;
console.log(` 2.${result}`);
return 'result';
}
let genObj = dataConsumer();
genObj.next(); // {value: undefined, done: false}
// Started
genObj.next('a'); // {value: undefined, done: false}
// 1. a
genObj.next('b'); // {value: "result", done: false}
// 2. b
Copy the code
for… Of circulation
for… The of loop automatically iterates over the Iterator generated when the Generator function is running, and there is no need to call the next method.
function* foo () {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
return 6;
}
for (const v of foo()) {
console.log(v);
}
Copy the code
Note that once the next method returns an object with the done attribute true, for… The of loop terminates and does not contain the return object, so the 6 returned by the return statement above is not included in the for… In the loop of.
However, code after Yield 5 is executed.
abnormal
Each traverser object returned by a Generator function has a throw method that throws an error outside the function and then catches it inside the Generator.
const g = function* () {
try {
yield;
} catch(e){
console.log('Internal capture', e);// Catch the first throw of the I object}};const i = g();
i.next();
try {
i.throw('a');// Throw an error outside the function, catch an error inside the function
i.throw('b');// Throw an error outside the function, catch an error outside the function
} catch (e) {
console.log('External capture', e);
}
/ / the result
// Internally capture a
// External capture b
Copy the code