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