Generator

作者: jluemmmm | 来源:发表于2020-08-19 16:40 被阅读0次

    Generator函数是一个状态机,封装了多个内部状态。同时Generator还是一个遍历器对象生成函数,执行Generator函数会返回一个遍历器对象,返回的遍历器对象可以依次遍历Generator函数内部的每一个状态。其特征如下:

    • function关键字与函数名之间有一个星号
    • 函数体内部使用yield表达式,定义不同的内部状态
    function* helloWorld() {
      yield 'hello'
      yield 'world'
      return 'ending'
    }                                                                                                                                                                                                                                                                                                                                                                                                                                                
    var hw = helloWorld()
    hw.next()
    // {value: "hello", done: false}
    hw.next()
    // {value: "world", done: false}
    hw.next()
    // {value: "ending", done: true}
    hw.next()
    // {value: undefined, done: true}
    

    调用Generator函数后,返回的是一个指向内部状态的指针对象。调用遍历器对象的next方法,使得指针下移一个状态,内部指针从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式。

    遍历器对象的 next 方法运行逻辑:

    1. 遇到 yield 语句暂停执行后面的操作,并将紧跟在 yield 后面的表达式的值作为返回的对象的 value 属性值
    2. 下一次调用 next 方法时再继续往下执行,直到遇到下一条yield语句
    3. 如果没有再遇到新的 yield语句,一直运行到函数结束,直到 return 语句为止,并将return 语句后面的表达式的值作为返回对象的 value 属性值
    4. 如果该函数没有 return 语句,返回对象的value 属性值为 undefined

    yield 语句本身没有返回值,next 方法可以带有一个参数,该参数会被当作上一条 yield 语句的返回值

    function * foo(x) {
      var y = 2 * ( yield (x + 1) )
      var z = yield (y / 3)
      return (x + y + z)
    }
    
    // yield 语句的值就是调用 next 方法的返回值
    
    var a = foo(5)
    a.next() // 6
    a.next() // NaN :------ next 方法不带参数, y 的值为 2 * undefined
    a.next() // NaN 
    
    var b = foo(5) // 如果调用方法传入 next 值, next 传入的值会被当作上一条 yield 语句的返回值
    b.next() // 6 ------- y: 12
    b.next(12) // 8 ------y: 24, z: 4
    b.next(13) // x: 5; y: 24; z: 13 ------- 42
    

    对象的Symbol.interator方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象,由于Generator函数就是遍历器生成函数,可以把Generator函数赋给Symbol.iterator属性,从而使得该对象具有Interator接口。

    var iter = {};
    iter[Symbol.iterator] = function* () {
      yield 1;
      yield 2;
      yield 3;
    };
    [...iter]
    

    for...of 循环可以自动遍历 Generator 函数生成的 Iterator 对象,不再需要调用 next 方法。当 next 方法返回的对象的 done 属性为 true 时,for...of 循环会终止,且不包含该返回对象,return 语句返回值不会出现在 for...of 循环中

    对象不具备原生 Iterator 接口,可以自行定义实现

    let jane = {
      first: 'Jane',
      last: 'Doe'
    }
    
    function * objEnt() {
      let propKeys = Object.keys(this)
      for(let key of propKeys) {
        yield [key, this[key]]
      }
    }
    
    jane[Symbol.iterator] = objEnt
    
    for(let [key, value] of jane) {
      console.log(`${key}: ${value}`)
    }
    

    for...of 循环,扩展运算符,解构赋值和Array.from 方法内部调用的都是遍历器接口,可以将 Generator 函数返回的 Iterator 对象作为参数

    相关文章

      网友评论

          本文标题:Generator

          本文链接:https://www.haomeiwen.com/subject/lyarjktx.html