JavaScript基础:生成器

概述

JavaScript中函数一旦启动运行,在它结束之前是不会被中断的。但在ES6中引入了一个全新的函数形式生成器Generator。这种函数不像普通函数一样保证执行运行到结束,而是具有函数块内暂停和恢复代码执行的能力。生成器Generator的形式只是在普通函数名称之前加一个*表示这是一个生成器。其特征主要有两个:1、function关键字与函数名之间有一个星号;2、函数体内部使用关键字yield表达式,定义不同的内部状态。生成器Generator的使用与普通函数一样,只是调用生成器函数会产生一个迭代器,因此可以调用迭代器的next函数让函数开始或恢复执行。

// 这是一个 Generator

function *genFunc () {
  yield 'generator';
  yield 'hello';
  yield 'word';
  return '!';
}

const it = genFunc();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

如下其执行结果就是迭代器产生的内容:

gen的log结果

yield关键字

生成器通过使用yield关键字便是暂停点。也就是说,生成器函数遇到yield关键字之前会正常执行,遇到该关键字时,执行会暂停函数的作用域状态会被保留下来,直到调用next()函数恢复执行。此时的yield关键字有点像是函数的中间返回语句,它生成的值会出现在next()返回的对象里。yield关键字只能用在生成器函数内部,其它地方会抛出错误。

// 普通函数使用 yield

function func () {
  yield '测试 yield关键字的使用';
}

报错

yield* 表达式

如何在生成器函数中调用另一个生成器函数,理论上需要在函数体内手动遍历执行另一个生成器函数。

function *gen1 () {
  yield 'gen1: hellow';
  yield 'gen1: word';
  return 'gen1';
}

function *gen2 () {
  for (const genValue of gen1()) {
    console.log(genValue);
  }
  yield 'gen2: hellow';
  yield 'gen2: word';
  return 'gen2';
}

const it = gen2();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

手动迭代的结果

ES6提供了yield*表达式即是yield委托(yield delegation)解决此类问题。yield* ...需要一个iterable对象,然后它会调用iterable的迭代器,把自己的生成器控制委托到这个迭代器,直到其耗尽为止。

function *gen3 () {
  const genValue = yield* gen1();
  console.log('genValue:', genValue);
  yield 'gen3: hellow';
  yield 'gen3: word';
  return 'gen3';
}

const it = gen3();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

yield*的结果
因此可以使用yield*表达式实现递归操作。

function *genMult (x) {
  if (x < 3) {
  	x = yield* genMult(x + 1);
  }
  return x * 2;
}

const it = genMult(1);
it.next(); // {value: 24, done: true}
yield输入和输出

yield既可以作为函数的中间返回语句使用,也可以作为函数的中间参数使用。yield表达式本身没有返回值,或者说总是返回undefinednext方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。

function *sum (x) {
  const y = yield;
  const z = yield;
  return x + y + z;
}

const it = sum(1);
console.log(it.next());
console.log(it.next(2));
console.log(it.next(3));

yield输入
其中第一次调用next出入的值不会被使用,因为第一次调用是为了开始执行生成器函数。

提前终止生成器

与迭代器类似可以使用returnthrow提前结束跌倒器的状态,生成器也是可以使用returnthrow方法提前终止生成器。return方法会强制生成器进入关闭状态,return方法传入的值,就是终止生成器的值。切后续关闭状态无法恢复,后续再次调用next方法done: true会一直保持。

function *returnFunc () {
  yield 1;
  yield 2;
  yield 3;
}

const it = returnFunc();
console.log(it.next());
console.log(it.return(4));
console.log(it.next());

return的log
return方法除了关闭生成器之外,如何生成器函数中包含finally子句,还可以执行情路任务如何资源释放、状态重置等。也就是说如果生成器函数内部有try...finally代码块,且正在执行try代码块,那么return()方法会导致立刻进入finally代码块,执行完以后,整个函数才会结束。

function *returnFunc () {
  try {
    yield 1;
    yield 2;
  } finally {
    yield 3;
    yield 5;
  }
}

const it = returnFunc();
console.log(it.next());
console.log(it.return(4));
console.log(it.next());
console.log(it.next());

finally的值
注意调用return()方法后,就立即执行finally代码块,不执行try里余下的代码了,然后等到finally代码块执行完,再返回return()方法指定的值。

throw方法会在暂停的时候将一个提供的错误注入到生成器对象中,相当于在暂停点出入一个throw ...。如果生成器内部有catch模块对错误进行处理,那么生成器就不会关闭,而且还可以恢复执行。

function *throwFunc () {
  try {
    yield 1;
    yield 2;
  } catch (e) {
  	console.error(e);
    yield 3;
    yield 5;
  }
}

const it = throwFunc();
console.log(it.next());
console.log(it.throw(new Error('throw error')));
console.log(it.next());

throw的log结果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GitHub上有很多开源的代码生成器,这些代码生成器可以帮助开发人员快速生成项目代码,提高开发效率。其中一些知名的代码生成器包括: 1. MyBatis Generator:这是一个专门针对Java开发的代码生成器,它可以通过解析数据库表结构,自动生成与数据库交互的持久层代码。开发人员只需要编写简单的XML配置文件,就可以轻松生成数据库表对应的实体类、DAO接口和映射文件。使用MyBatis Generator可以省去大量的重复劳动,提高代码的可读性和可维护性。 2. CodeIgniter CLI:CodeIgniter是一款流行的PHP框架,它提供了一个命令行界面(CLI)工具,可以帮助开发人员快速生成代码。通过CLI工具,开发人员可以生成控制器、模型、视图等常用的文件和目录结构,减少手动编写重复代码的工作量。这个代码生成器可以大大提升CodeIgniter框架的开发效率。 3. JHipster:这是一个用于生成现代化Web应用的工具。JHipster可以帮助开发人员快速搭建基于Java和JavaScript的应用架构,包括Spring Boot、Angular/React/Vue.js等技术栈的集成。通过JHipster,开发人员只需要回答一些基本配置问题,就可以自动生成整个项目的基础代码、数据库模型和前端页面等。这个代码生成器可以帮助开发人员节省大量的时间,快速创建现代化的Web应用。 总结起来,GitHub上的开源代码生成器提供了一种便捷的方式,可以帮助开发人员快速生成项目代码,减少重复劳动,提高开发效率。无论是针对不同的编程语言还是不同的应用场景,都可以找到适合自己的代码生成器,加快开发进度,降低开发成本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值