2021.7.12 Generator生成器函数

Generator生成器函数在JavaScript中用于创建可迭代对象,它们遵循迭代器协议。通过在function关键字后加上*创建生成器函数。执行生成器函数不立即执行代码,而是返回一个符合迭代器规范的实例。这个实例具有next、return和throw方法,以及Symbol.iterator和Symbol.toStringTag等私有属性。生成器函数不同于普通函数,它们是GeneratorFunction的实例,并且不能作为构造函数使用。在生成器中,next方法用于前进并返回done和value,可以传递值给生成器,而return和throw方法分别用于结束生成器并返回指定值以及抛出异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Generator生成器函数

生成器对象是由一个generator function返回的,并且它符合可迭代协议和迭代器协议。
生成器函数就是用来生成迭代器的。
如何创建一个生成器函数?
创建函数时,在function后加一个“星号 *”,则创建的函数为生成器函数

function* fn() {
    console.log(this);
    return 10;
}
  • 把生成器函数 [fn] 执行,函数体中的代码并没有立即执行,而是而是创建了 [fn] 这个类的一个实例 [inst]
  • inst.proto === fn.prototype
  • inst这个对象,是符合迭代器规范的
    • 有三个方法
      • next
      • return
      • throw
    • 有一些私有属性
      • Symbol(Symbol.iterator)
      • Symbol(Symbol.toStringTag): “Generator”

普通函数VS生成器函数

  • [把它当作一个实例__proto__]
    • 普通函数是 Function 的实例,普通函数.proto===Function.prototype
    • 生成器函数是 GeneratorFunction 的实例
      • 生成器函数.proto===GeneraorFunction.prototype
      • GeneratorFunction.prototype.proto===Function.prototype
      • Object.toString.call(生成器函数) 结果是:"[object GeneratorFunction]"
  • [把它作为一个构造函数 prototype]
    • 生成器函数不能被new执行 Uncaught TypeError: func is not a constructor
    • 当作普通函数执行,返回的结果就是生成器函数的一个实例
    • inst.proto -> func.prototype「空对象,没有constructor」 -> Generator.prototype「constructor:GeneratorFunction」{next/return/throw/Symbol(Symbol.toStringTag): “Generator”} -> 一个具备迭代器规范的对象「Symbol(Symbol.iterator)」 -> Object.prototype

Generator.prototype.next()
next()方法返回一个包含 done 和 value 的对象,该方法也可以接收一个参数以向生成器传值

  • 语法:gen.next(value)
  • 参数:value 向生成器传递的值
  • 返回值:
    function* generator() {
      console.log('A');
      yield 10;
      console.log('B');
      yield 20;
      console.log('C');
      yield 30;
      console.log('D');
      return 40;
    }
    let inst = generator();
    // 每一次执行next,遇到yeild则结束;yeild后面的值,就是每一次返回对象中的value值;
    console.log(inst.next()); //输出‘A’  结果{value:10,done:false}
    console.log(inst.next()); //输出‘B’  结果{value:20,done:false}
    console.log(inst.next()); //输出‘C’  结果{value:30,done:false}
    console.log(inst.next()); //输出‘D’  结果{value:40,done:true}
    console.log(inst.next()); //结果{value:undefined,done:true}
    
  • next方法给生成器传值
    • 每一次执行next传递进来的值,是给上一个yeild的返回值赋值
    • 第一次调用next方法,传参没有意义
    function* generator() {
        let x1 = yield 10;
        console.log(x1);
        let x2 = yield 20;
        console.log(x2);
        return 30;
    }
    let itor = generator();
    // 每一次执行next传递进来的值,是给上一个yeild的返回值赋值「第一次执行next传递进来的值是没用的」
    console.log(itor.next('AA')); //没有输出  {value:10,done:false}
    console.log(itor.next('BB')); //输出“BB”  {value:20,done:false}
    console.log(itor.next('CC')); //输出“CC”  {value:30,done:true}
    console.log(itor.next('DD')); //{value:undefined,done:true}
    
  • 如果再一个生成器中加入另外一个生成器,则迭代的时候会进入新的生成器中迭代
    function* generator1() {
        yield 10;
        yield 20;
    }
    
    function* generator2() {
        yield 30;
        yield* generator1();
        yield 40;
    }
    let itor = generator2();
    console.log(itor.next()); //value:30
    console.log(itor.next()); //value:10  加了yield*,则进入新的generator中迭代
    console.log(itor.next()); //value:20
    console.log(itor.next()); //value:40
    

Generator.prototype.return()

  • 语法:gen.return(value)
  • 参数:value 需要返回的值
  • 返回值:返回该函数参数中给定的值
    function* gen() {
      yield 1;
      yield 2;
      yield 3;
    }
    
    var g = gen();
    
    g.next();        // { value: 1, done: false }
    g.return("foo"); // { value: "foo", done: true }
    g.next();        // { value: undefined, done: true }
    
    

Generator.prototype.throw()

  • 语法:gen.throw(exception)
  • 参数:exception 用于抛出的异常。 使用 Error 的实例对调试非常有帮助
  • 返回值:
    function* gen() {
      while(true) {
        try {
           yield 42;
        } catch(e) {
          console.log("Error caught!");
        }
      }
    }
    
    var g = gen();
    g.next(); // { value: 42, done: false }
    g.throw(new Error("Something went wrong")); // "Error caught!"
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值