current position:Home>Front end learning notes -- ES6 generator

Front end learning notes -- ES6 generator

2021-08-27 05:41:38 Atomic

generator

One 、 Basic concepts

Generator The function is ES6 A kind of Asynchronous programming Solution , Grammatical behavior is totally different from traditional function .

Generator There are many ways to understand functions . Grammatically , First of all, it can be understood as ,Generator Function is a State machine , Encapsulates multiple internal states .

perform Generator Function returns a traverser object , in other words ,Generator Function except state machine , It's also a traverser object generation function . Back to Traverser object , You can traverse through Generator Every state inside a function .

  function * helloGenerator(){
        yield "h";
        yield "e";
        yield "l";
        yield "l";
        yield "o";
        return ;
    }
    const iterator = helloGenerator();
 Copy code 

To sum up , call Generator function , Returns a traverser object , representative Generator Function's internal pointer . in the future , Every time I call the next Method , Will return to one with value and done Objects with two properties . value Property represents the value of the current internal state , yes yield The value of the expression after the expression ; done Property is a Boolean value , Indicates whether the traversal ends .

Two 、yield expression

because Generator The traverser object returned by the function , Only a call next Method to traverse the next internal state , So it actually provides a function that can pause execution .yield The expression is Pause symbol .

Of the traverser object next The operation logic of the method is as follows .

(1) encounter yield expression , Just pause the next operation , And will follow closely yield The value of the expression that follows , As the returned object value Property value .

(2) Next call next When the method is used , Go on and on , Until we meet the next one yield expression .

(3) If there is no new yield expression , It runs until the end of the function , until return The statement so far , And will return The value of the expression after the statement , As the returned object value Property value .

(4) If the function doesn't have return sentence , Of the returned object value The property value is undefined .

It should be noted that , yield The expression after the expression , Only when called next Method 、 Only when the internal pointer points to the statement , So it's equal to JavaScript Provides manual “ Lazy evaluation ”(Lazy Evaluation) The grammatical function of .

yield And return Compare :

  1. identical : Can return the value of the expression immediately following the statement
  2. Different : The difference is that every time I meet yield , Function pause , Next time, continue backward from this position , and return The sentence does not have the function of position memory . In a function , It can only be executed once ( Or a ) return sentence , But it can be done many times ( Or more ) yield expression . A normal function can only return one value , Because it can only be executed once return ;Generator Function can return a series of values , Because there can be as many yield . Look at it from another Angle , It can also be said that Generator Generated a series of values , This is the origin of its name ( In English ,generator The word is “ generator ” It means )

Generator Functions can be used without yield expression , This becomes a simple delay function .

yield Expressions can only be used in Generator In the function , It's wrong to use it in other places .

yield Expression if used in another expression , Must be in parentheses .

yield An expression is used as a function parameter or placed to the right of an assignment expression , I don't have to put in parentheses .

3、 ... and 、 And Iterator Interface relationship

Of any object Symbol.iterator Method , Equal to the traverser generator function of the object , Calling this function returns a traverser object of the object .

because Generator A function is a traverser generating function , So we can Generator Assigned to the object Symbol.iterator attribute , So that the object has Iterator Interface .

Four 、next Method parameters

yield The expression itself does not return a value , Or always back undefined .

 function * f2(){
        console.log(yield 1);
    }
    const iter = f2();
    iter.next() // {"value": 1,"done": false}
    iter.next() // undefined {"value":undefined,done:true}
		
		//  First execution yield 1 , Return an object , Pause .
		//  The second time, proceed to console.log(), because yield The expression has no return value , So print out undefined
    
 Copy code 

next Method can take a parameter , This parameter will be taken as the last yield Return value of expression .

    function* gen() {
        while (true) {
            let reslut = yield "hello";
            console.log("reslut:", reslut);
        }
    }
    const gens = gen();
    gens.next(); //  No output , perform yield Then it paused ( On the right side of the assignment operator, execute ).
    gens.next();  //  Continue the assignment operation , because yield The expression has no return value , all resule yes undefined
    gens.next("world") //  Take the parameter as the last yield Return value of expression ,result The assignment is world
 Copy code 

This function has very important grammatical meaning .Generator Function from suspend to resume , Its context state (context) It is the same. . adopt next Method parameters , There is a way Generator After the function starts to run , Continue to inject value into function body . in other words , Can be in Generator Different stages of function operation , Inject different values from the outside to the inside , So we can adjust the function behavior .

5、 ... and 、for...of

for...of The loop can automatically traverse Generator Function generated at run time Iterator object , And there is no need to call next Method .

    function* foo() {
        yield 1;
        yield 2;
        yield 3;
        yield 4;
        yield 5;
        return 6;
    }
    for (let v of foo()) {
        console.log(v);
    }
 Copy code 

The above code USES for...of loop , Show... In turn 5 individual yield Value of expression . Here we need to pay attention to , once next Method of the return object done The attribute is true , for...of The cycle will stop , And does not contain the return object , So the code above return Statement returned 6 , Not included in for...of In the cycle .

6、 ... and 、yield* expression

If in Generator Internal function , Call another Generator function . It needs to be inside the function body of the former , Complete the traversal by yourself .

    function * f1(){
        yield 1;
        yield 2;
    }

    function * f2(){
        yield 'start';
        yield* f1();
        yield 'end'
    }
    const iter = f2();
    for(let value of iter){
        console.log(value)
    }
    
   //  Output 
   // start
   //1
   //2
   //end
 Copy code 

Compared to using yield:

function * f1(){
        yield 1;
        yield 2;
    }

    function * f2(){
        yield 'start';
        yield f1();
        yield 'end'
    }
    const iter = f2();
    for(let value of iter){
        console.log(value)
    }
    
    //  Output 
    // start
    // f1 <generator>  
    //end
    
    // yield f1() Returns an iterator object , Instead of the internal value of the iterator 
 Copy code 

From a grammatical point of view , If yield The expression is followed by an iterator object , Need to be in yield Put an asterisk after the expression , Indicates that it returns a traverser object . This is known as yield* expression .

If the agent Generator Function has return sentence , Then you can send it to the agent Generator Function returns data .

If the property of an object is Generator function , It can be abbreviated to the following form .

let obj = {
  * myGeneratorMethod() {
    ···
  }
};

//  Complete writing 
let obj = {
  myGeneratorMethod: function* () {
    // ···
  }
};
 Copy code 

7、 ... and 、Generator Functional this

Generator Functions always return an iterator ,ES6 Specify that this traverser is Generator Examples of functions , Also inherited Generator Functional prototype Method on object .

 function * gen(){
        this.name = "hello"
    }

    gen.prototype.say = function(){
        console.log("world")
    }
    let g = gen(); 
    console.log(g instanceof gen);  //true
    g.say();// world
    console.log(g.name) //undefined
 Copy code 
g.name  yes undefined , because  gen Always return the traverser object , instead of  this  object .

 Copy code 

Generator Functions can't follow new Command together , Will report a mistake .

Generator Asynchronous application of function

copyright notice
author[Atomic],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2021/08/20210827054135737x.html

Random recommended