1、入门

function* fn() {console.log(1);//暂停!yield;//调用next方法继续执行console.log(2);
}
var iter = fn();
iter.next(); //1
iter.next(); //2

生成器解析如下:
1、函数生成器特点是函数名前面有一个‘*’

2、通过调用函数生成一个控制器

3、调用控制器的next()方法开始执行函数

4、遇到yield函数将暂停

5、再次调用控制器的next() 继续执行函数

yield关键词并不会像return一样立即结束函数,只是暂停这个生成器函数,直到下一次调用next方法会继续从yield位置向下执行。

generator的特点

  • 每当执行完一条yield语句后函数就会自动停止执行, 直到再次调用next();

  • yield关键字只可在生成器内部使用,在其他地方使用会导致程序抛出错误

  • 可以通过函数表达式来创建生成器, 但是不能使用箭头函数

  • 可以在generator函数运行的不同阶段从外部内部注入不同的值,从而改变函数的行为

  • yield语句无返回值,总是返回undefined

  • next方法可以带一个参数,参数被当做上一条yield的返回值。

function* generator() {const list = [1, 2, 3];for (let i of list) {yield i;} }
let g = generator();
console.log(g.next()); // {value: 1, done: false}
console.log(g.next()); // {value: 2, done: false}
console.log(g.next()); // {value: 3, done: false}
console.log(g.next()); // {value: undefined, done: true}function* foo(x){var y = 2 * (yield(x + 1));var z = yield (y / 3);return (x + y + z);
}var a = foo(5);
a.next() //{value: 6, done: false}
a.next() //{value: NaN, done: false}, 2* undefined / 3 = NaN
a.next() //{value: NaN, done: true}, 5 + NaN + undefined = NaNvar b = foo(5)
b.next() //{value: 6, done: false}
b.next(12) //{value: 8, done: false}  2 * 12 / 3 = 8
b.next(13) //{value: , done: true} 5 + 2 * 12 + 13 = 42

2、消息传递

除了暂停和继续执行外,生成器同时支持传值。
在函数的内容可以使用yield的关键词向外返回一个值,在next方法调用的时候可以拿到这个值

2.1、Demo1
function* fn() {var a = yield 'hello';yield;console.log(a);
}
var iter = fn();
var res = iter.next();
console.log(res);
iter.next(2);
iter.next(); //2

解析如下:
1、可以看到,yield后面有一个字符串‘hello’,在第一次调用next时,暂停在这里且返回给了iter.next(),即res = {done:false,value:‘hello’}

2、由于暂停的地方是一个赋值语句,需要一个变量给a,于是第二个next()方法中传了一个参数2替换了yield,最后打印a得到了2。

2.2、demo2
function *foo(x) {let y = 2 * (yield (x + 1))let z = yield (y / 3)return (x + y + z)
}
let it = foo(5)
console.log(it.next())   // => {value: 6, done: false}
console.log(it.next(12)) // => {value: 8, done: false}
console.log(it.next(13)) // => {value: 42, done: true}

分析如下:

  • 首先 Generator 函数调用和普通函数不同,它会返回一个迭代器
  • 当执行第一次 next 时,传参会被忽略,并且函数暂停在 yield (x + 1) 处,所以返回 5 + 1 = 6
  • 当执行第二次 next 时,传入的参数12就会被当作上一个yield表达式的返回值,如果你不传参,yield 永远返回 undefined。此时 let y = 2 * 12,所以第二个 yield 等于 2 * 12 / 3 = 8
  • 当执行第三次 next 时,传入的参数13就会被当作上一个yield表达式的返回值,所以 z = 13, x = 5, y = 24,相加等于 42

3、yield与next()的使用

function* foo(x) {console.log('first');var y = 2 * (yield (x + 1));console.log('second');var z = yield (y / 3);console.log('third');return (x + y + z);
}var a = foo(5);
a.next() // first   Object{value:6, done:false}
a.next() // second  Object{value:NaN, done:false}
a.next() // third   Object{value:NaN, done:true}    var b = foo(5);
b.next() // first  { value:6, done:false }
b.next(12) // second   { value:8, done:false }
b.next(13) // third { value:42, done:true }
  • 首次调用next()方法表示开始执行generator函数

  • 之后在执行时遇到yield表达式,就暂停执行yield表达式之后的操作,但是yield表达式要执行,并且将yield表达式之后的值作为返回对象的value值

    比如说上面的generator函数,
    第一次调用next(),yield表达式x+1会执行,但是2*(yield (x+1))并不会执行

  • 再次调用next(val)方法,继续向下执行,同时val参数可作为yield返回对象的value值,继续向下执行,如果没有传则默认为NaN。如此往复,直到执行完毕。

注意:yield返回的对象中done表示执行状态,是否执行完毕

4、生成器函数封装如下

const fetchData = (arg) => new Promise(resolve => {setTimeout(() => {resolve('test data ' + arg)}, 3000)
})// generator 函数最终返回一个Promise对象
// generator 中遇到yield, 先执行其后操作,等执行完成后,执行完next()方法,才能继续向下执行
function* test() {console.log('0')let res = yield fetchData('1')console.log('1', res)res = yield fetchData(res)console.log('2', res)res = yield fetchData(res)console.log('3', res)res = yield fetchData(res)console.log('4', res)
}// 自动执行器run
const run = g => {       const next = val => {const res = g.next(val)if(res.done) return res.valueres.value.then(next)}next()
}run(test())

输出结果如下

参考地址:https://blog.csdn.net/qinshengnan520/article/details/108287199

js中的生成器函数Generator相关推荐

  1. 如何用python生成软件_python中的生成器函数是如何工作的?

    1. python中的普通函数是怎么运行的? 当一个python函数在执行时,它会在相应的python栈帧上运行,栈帧表示程序运行时函数调用栈中的某一帧.想要获得某个函数相关的栈帧,则必须在调用这个函 ...

  2. jsp value设置为函数的返回值_python中的生成器函数是如何工作的?

    1. python中的普通函数是怎么运行的? 当一个python函数在执行时,它会在相应的python栈帧上运行,栈帧表示程序运行时函数调用栈中的某一帧.想要获得某个函数相关的栈帧,则必须在调用这个函 ...

  3. ES6生成器函数generator

    ES6生成器函数generator generator是ES6新增的一个特殊函数,通过 function* 声明,函数体内通过 yield 来指明函数的暂停点,该函数返回一个迭代器,并且函数执行到 y ...

  4. js中的offset函数和position

    js中的offset函数,其本身是个对象,它含有两个属性,top和left,其属性值是数字,无单位,是针对文档内容的,即浏览器 而position函数,也有上述两个属性,但它是针对父元素的偏移量 转载 ...

  5. php new对象 调用函数,关于JS中new调用函数的原理介绍

    这篇文章主要介绍了关于JS中new调用函数的原理介绍,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 JavaScript 中经常使用构造函数创建对象(通过 new 操作符调用一个函数) ...

  6. js中同名的函数的调用情况

    转自:https://www.cnblogs.com/wshiqtb/p/3480597.html html中如果出现函数同名时: 如果有多个外部引入的js文件,例如a.js和b.js(引入顺序假定是 ...

  7. JS中自动执行函数小结

    JS中自动执行函数小结 请看以下两个函数: 1.function a(){ 2.    alert("a") 3.} 1.var b= function(){ 2.    aler ...

  8. underscore.js中的节流函数debounce及trottle

    函数节流   throttle and debounce的相关总结及想法 一开始函数节流的使用场景是:放止一个按钮多次点击多次触发一个功能函数,所以做了一个clearTimeout setTimeou ...

  9. Vue.js 中的渲染函数是什么?如何使用渲染函数?

    Vue.js 中的渲染函数是什么?如何使用渲染函数? Vue.js 是一款流行的前端框架,它提供了许多方便的工具和 API,用于构建交互式的用户界面.其中,渲染函数是 Vue.js 中一个强大的工具, ...

  10. js中写一个函数,第一秒打印1,第二秒打印2

    js中写一个函数,第一秒打印1,第二秒打印2 1.用let块级作用域 for(let i = 0;i<5;i++){setTimeout(()=>{console.log(i);},100 ...

最新文章

  1. 新视界,你好!_只愿与一人十指紧扣_新浪博客
  2. lvm实现快速备份文件及数据库,lvm快照原理
  3. 每日一皮:老大爷,您保持年轻的秘诀是什么
  4. 深度学习手势识别带你玩转神庙逃亡
  5. loaction.reload(false)和location.reload(true) js发起请求
  6. HDU 2896 病毒侵袭【AC自动机】
  7. 操作系统的msxml组件版本过低_Zabbix 5.0 LTS 版本安装
  8. 小程序 Typescript 最佳实践
  9. 260多媒体语言如何调节_260马力配9.7米货厢,实拍柳汽H5小三轴载货车
  10. SQL-22 统计各个部门对应员工涨幅的次数总和,给出部门编码dept_no、部门名称dept_name以及次数sum...
  11. 进一步理解VC中的句柄
  12. 混合分布(mixture distribution)
  13. 一般试卷的纸张大小是多少_试卷字体多大合适 标准试卷的字体大小
  14. 对于div背景颜色的透明
  15. 巨杉数据库兼容mysql_SequoiaDB 巨杉数据库
  16. 基本:HEX文件格式定义
  17. 2019 CCCC 天梯赛 杭州站 历程
  18. 北京第一年-OpenGL-19-沉淀
  19. 使用ffmpeg进行简单的视频编辑
  20. 互联网指标体系构建及分析方法

热门文章

  1. 初识二维码 第十八讲 编码转换
  2. 云信api_网易数帆开源贡献获业界肯定,轻舟API网关获OSCAR尖峰开源技术创新奖...
  3. 养老保险个人帐户说明[南京]
  4. vue使用file-saver本地文件导出
  5. 最新支付宝蚂蚁森林自动偷能量,解放双手
  6. 【为人处事】:如何识人
  7. 【技术】怎么将PPT中的白底图片,白色部分变透明?
  8. C/C++项目:魂斗罗游戏
  9. 路由器 OSPF 动态路由配置
  10. 本地IDEA连接服务器的Redis报错处理