ES6: Los entresijos del generador

ES6: Los entresijos de Generator

Visión general

  • La función de generador es una solución de programación asíncrona proporcionada por ES6, que puede entenderse como una máquina de estados que encapsula múltiples estados internos. -

  • La ejecución de la función Generator devolverá un objeto traverser, que puede atravesar cada estado dentro de la función por turno;

  • La función Generador tiene dos características:

    • Hay un asterisco entre la función y el nombre de la función;
    • La declaración de rendimiento se utiliza dentro del cuerpo de la función para definir diferentes estados internos.
  • Ejemplo:

    function*helloWorldGenerator(){
          
          
        yield '听不见!';
        yield '重来!';
        return '很有精神!'
    }
    let hw = helloWorldGenerator();
    
    hw.next();	// { value : '听不见!',done : false }
    hw.next();	// { value : '重来!',done : false }
    hw.next();	// { value : '很有精神!',done : true }
    hw.next();	// { value : undefined , done : true }
    
  • Con esta función, puede realizar el mecanismo de programación asincrónica de la función;

expresión de rendimiento

  • El mecanismo de ejecución del siguiente método del traverser es el siguiente:

    1. Cuando se encuentre una declaración de rendimiento, la ejecución de las siguientes operaciones se suspenderá y el valor de la expresión de rendimiento se devolverá como el valor del atributo de valor del objeto devuelto;
    2. La próxima vez que se llame a la siguiente llamada para continuar la ejecución, hasta que se encuentre la siguiente declaración de rendimiento;
    3. Si no hay rendimiento, ejecute directamente a la declaración de retorno;
    4. Si no hay una declaración de retorno, se devuelve un objeto cuyo valor no está definido.
  • El rendimiento debe colocarse en la función Generador antes de que pueda usarse;

  • Si se usa rendimiento en otra expresión, ¡se deben agregar paréntesis!

    console.log('hello' + yield 123); ///error
    console.log('hello' + (yield 123));  //ok 
    

Parámetros del siguiente método

  • El siguiente método puede tomar un parámetro, que se utilizará como valor de retorno de la declaración anterior. Cuando next no tiene parámetros, devuelve undefined;

    function* f(){
          
          
        for(let i=0;ture;i++){
          
          
            let reset = yield i;
            if(reset){
          
          
                i = -1;
            }
        }
    }
    
    let g = f();
    g.next()	//{value : 0,done : false};
    g.next()	//{value : 1,done : false};
    g.next(true)	//{value : 0,done : false};
    

para ... de método

  • El bucle for ... of puede atravesar automáticamente el objeto Iterator generado por la función Generator, eliminando la necesidad de utilizar el siguiente método;

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

rendimiento * expresión

  • Si llama a otra función de generador en un generador, el valor predeterminado es sin efecto;

    function* foo(){
          
          
        yield 'a';
        yield 'b';
    }
    
    function bar(){
          
          
        yield 1;
        foo();
        yield 2;
    }
    
    for(let i of bar()){
          
          
        console.log(i);
    }
    
    >>1
    >>2
    
  • Puede verse que la llamada directa no puede ejecutar foo () en for ... of;

  • En este momento, debe usar la declaración yield *, por lo que el código anterior se puede modificar de la siguiente manera:

    function* foo(){
          
          
        yield 'a';
        yield 'b';
    }
    
    function bar(){
          
          
        yield 1;
        yield* foo();
        yield 2;
    }
    
    for(let i of bar()){
          
          
        console.log(i);
    }
    
    >>1
    >>'a'
    >>'b'
    >>2
    
  • Si rendimiento * va seguido de una matriz, los miembros de la matriz se atravesarán:

    function* foo(){
          
          
        yield [1,2,3,4,5];
    }
    foo().next();	//[1,2,3,4,5]
    
    function* foo(){
          
          
        yield* [1,2,3,4,5];
    }
    foo().next();	//{value : 1,done : false}
    
  • La expresión yield * puede atravesar rápidamente todos los miembros de la matriz anidada;

    function* iterTree(tree){
          
          
        if(Array.isArray(tree)){
          
          
            for(let i=0;i<tree.length;i++);
            yield* iterTree(tree[i]);
        }else{
          
          
            yield tree;
        }
    }
    
    
    const tree = [1,[2,3],[4,5]];
    for(let x of iterTree(tree)){
          
          
        console.log(x);
    }
    
    >> 1
    >> 2
    >> 3
    >> 4
    >> 5
    

Esto de la función Generador

  • El iterador devuelto por la función Generator es una instancia de la función Generator original, que también hereda el prototipo de la función original;

  • Por lo tanto, el iterador de la función Generator no puede acceder directamente a las propiedades de la función original;

    function* foo(){
          
          
        this.a = 1;
    }
    
    let obj = foo();
    console.log(obj.a);			//undefined
    
  • Para obtener las propiedades de la función original, puede obtenerlas a través de un método flexible: use el método de llamada para vincularlo dentro de la función Generator;

    function* foo(){
          
          
        this.a = 1;
        yield this.b = 2;
        yield this.c = 3;
    }
    let obj = {
          
          };
    let bar = foo.call(obj); 
    
    bar.next();		//{value : 2 , done : false};
    bar.next();		//{value : 3 , done : false};
    
    console.log(obj.a)	// 1
    console.log(obj.b)	// 2
    console.log(obj.c)	// 3
    

Supongo que te gusta

Origin blog.csdn.net/yivisir/article/details/108476987
Recomendado
Clasificación