1. Call the generator function
Generator functions are an almost entirely new type of function that is completely different from standard, ordinary functions.
A generator function can generate a sequence of values, but each value is generated on a per-request basis, not immediately like a standard function.
// Define a generator function
function* WeaponGenerator(){
yield "Katana";
yield "Wakizashi";
yield "Kusarigama";
}
// Call generator to get an iterator
const weaponsIterator = WeaponGenerator();
// Manually call the.next methods in turn
// Each time the iterator's next method is called, a new value is requested from the generator
weaponsIterator.next();//{ value: 'Katana', done: false }
weaponsIterator.next();//{ value: 'Wakizashi', done: false }
weaponsIterator.next();//{ value: 'Kusarigama', done: false }
weaponsIterator.next();//{ value: undefined, done: true }
// Use a for-of loop
for (let item of WeaponGenerator()) {
console.log(item);Katana, Wakizashi, Kusarigama
}
Copy the code
2. Interacting with the generator (passing parameters)
function* WeaponGenerator(action){
const imposter = yield action;//imposter is the argument passed in the next call to next
yield imposter + "-" + action;
}
const weaponsIterator = WeaponGenerator("Sk");
weaponsIterator.next().value;//"Sk"
// The argument passed in the second call to next is the return value of the internal last call to yield
weaponsIterator.next("Hn").value;//"Hn - Sk"
Copy the code
Throw an exception
Each iterator has a throw method as well as a next method
function* WeaponGenerator(){
try{
yield "Hattori";
}
catch(e){
return e == "catch this"; }}const ninjaIterator = WeaponGenerator();
ninjaIterator.next()//{value: "Hattori", done: false}
ninjaIterator.throw("catch this")//{value: true, done: true}
Copy the code
4. Internal composition (execution principle)
Suspended start: When a generator is created, it first starts in this state. None of the code is executed
Execution: The execution state of code in a generator. Execution either begins or continues from the last time it was suspended. The generator moves to this state whenever the iterator corresponding to the generator calls the next method and there is currently executable code.
Suspend assignment: When a generator encounters a yield expression during execution, it creates a new object containing the return value and then suspends execution. The generator pauses in this state and waits for execution to continue.
Completed: During generator execution, the generator enters this state if the code executes to a return statement or if the global code completes execution
Generator function
function* WeaponGenerator(){
yield "Hattori";
yield "Yoshi";
}
Copy the code
Code execution process
// Create a generator and suspend it
const ninjaIterator = WeaponGenerator();
//2. Activate generator from suspend state to execute state. The yield "Hattori" statement terminates
{value: "Hattori", done: false}
const result1 = ninjaIterator.next();
//3. Reactivate the generator from the pending state to the executing state. Execute until the yield "Yoshi" statement terminates
{value: "Yoshi", done: false}
const result2 = ninjaIterator.next();
//4. Reactivate the generator from the pending state to the executing state.
{value: false, done: true}
const result3 = ninjaIterator.next();
Copy the code
Trace generator functions by executing the context
-
NinjaIterator: the execution stack points to the global execution context
- NinjaIterator: function
- Result1: undefined
- Result2: undefined
- Result3: undefined
-
NinjaIterator (0, 0); ninjaIterator (0, 0)
- Creates a new ninjaIterator object that points to the current generator context
- Create a new stack element and push it (ammunition Generator)
- Instead of executing any code, the function returns a new iterator; When the program is complete, the ammgenerator is ejected but not destroyed (due to ninjaIterator reference)
- The ammunition Generator execution context is temporarily suspended
- The execution stack point again points to the global execution context
-
Ninjaiterator.next () : > ammgenerator
- Reactivate the relevant context and push the ammunition Generator onto the stack
- When finished, suspend the execution context of the ammunition Generator again
- The execution stack point again points to the global execution context
-
4. Call ninjaiterator.next () and repeat the previous step
-
5. The execution is complete
5, iterations,
A wave of source code analysis
function createIterator(items) {
var i = 0
return {
next: function () {
var done = (i >= items.length)
varvalue = ! done ? items[i++] :undefined
return {
done: done,
value: value
}
}
[Symbol.iterator]: function () {
return this}}}var iterator = createIterator([1.2.3])
...iterator / / 1, 2, 3
Copy the code