从零开始学_JavaScript_系列(55)——Generator函数(3)yield*表达式
来源:互联网 发布:汤姆大叔 javascript 编辑:程序博客网 时间:2024/06/08 12:23
4、yield*表达式
4.1、基础
简单来说,yield*表达式就是在一个Generator函数内嵌套另外一个Generator函数。
于是在遍历的过程中,当在第一个Generator函数内遇见第二个Generator函数后,就会先停止遍历第一个Generator函数,先遍历完第二个Generator函数,然后再恢复。
如代码:
let g1 = function*() { yield 1; yield* g2(); yield 2;}let g2 = function*() { yield "a"; yield "b";}let foo = g1();for (let i of foo) { console.log(i)}// 1// a// b// 2
如上,简单暴力通俗易懂。
假如不是yield* g2()
,而是yield g2()
会发生什么事情呢?
- 首先,g2()会返回一个遍历器对象,毫无疑问;
- 其次,yield表达式会使得该遍历器对象作为next的返回值来返回;
- 因此最终结果是1——》g2()的遍历器——》2,代码就略了不写
4.2、递归
因为yield*表达式的存在,因此遍历器可以递归自己,代码十分简单:
let g1 = function*(count) { console.log("count:" + count) if (count > 3) { return } yield 1; yield 2; yield* g1(count + 1);}let foo = g1(1);for (let i of foo) { console.log(i)}// count:1// 1// 2// count:2// 1// 2// count:3// 1// 2// count:4
4.3、有Iterator接口的数据结构
yield*表达式可以遍历Generator函数,原因是Generator函数有Iterator接口,相当于对Generator函数的遍历器执行了for...of
;
那么yield*表达式能不能遍历非Generator函数,但是也有Iterator接口的数据结构呢?显然也是可以的。
如代码:
let g1 = function*() { yield* [1, 2] yield* "ab"}let foo = g1();for (let i of foo) { console.log(i)}// 1// 2// "a"// "b"
也可以对自定义数据结构生效,只要他有Iterator接口即可:
function Test() { let arr = [3, 2, 1] function Iterator() { let index = 0 // 该对象有next方法,调用后返回一个当前索引下的值 this.next = function () { let obj = {} if (index < 3) { obj.value = arr[index] obj.done = false index++ } else { obj.value = undefined obj.done = true } return obj } // 返回他自己 return this } // 遍历器接口 this[Symbol.iterator] = function () { // 创建一个遍历器对象(Iterator不是关键词) let temp = new Iterator() // 返回他 return temp }}let m = new Test()let g1 = function*() { yield* m}let foo = g1();for (let i of foo) { console.log(i)}// 3// 2// 1
4.4、返回值
- Generator函数是返回值是他的遍历器;
- 遍历器的返回值是对象,有value和done属性;
- yield表达式的返回值是根据遍历器的next的参数决定;
- 那么yield*表达式的返回值是什么呢?
答案是根据被遍历函数的return所决定;
最简单的示例如代码:
let g1 = function*() { console.log(yield* g2())}let g2 = function*() { yield 'a'; return 'b';}let foo = g1();for (let i of foo) { console.log(i)}// 'a'// 'b'
那么,是否还记得Generator函数的返回值在什么时候起作用?
可以回去看看1.1,return是在done第一次变为true时,value属性的值。
因此,yield*的值,取决于遍历器在遍历结束,done变为true时,value属性的值,如以下代码自定义了一个数据结构,这个数据结构在done变为true时是有值的。
function G() { let arr = [3, 2, 1] function Iterator() { let index = 0 this.next = function () { let obj = {} if (index < 3) { obj.value = arr[index] obj.done = false index++ } else { // 这里与之前的例子不同 obj.value = '自定义数据结构的done变为true了' obj.done = true } return obj } } this[Symbol.iterator] = function () { let temp = new Iterator() // 返回他 return temp }}let g = new G()let g1 = function*() { console.log(yield* g)}let foo = g1();for (let i of foo) { console.log(i)}// 3// 2// 1// "自定义数据结构的done变为true了"
阅读全文
0 0
- 从零开始学_JavaScript_系列(55)——Generator函数(3)yield*表达式
- 从零开始学_JavaScript_系列(62)——class(3)setter和getter、Generator、async函数
- 从零开始学_JavaScript_系列(57)——Generator函数(5)状态机与函数的应用
- 从零开始学_JavaScript_系列(53)——Generator函数(1)基本概念和示例
- 从零开始学_JavaScript_系列(54)——Generator函数(2)简单应用、throw和return
- 从零开始学_JavaScript_系列(56)——Generator函数(4)简写,this与继承
- 从零开始学_JavaScript_系列(58)——Thunk函数
- 从零开始学_JavaScript_系列(59)——async函数
- 从零开始学_JavaScript_系列(16)——js系列<5>(正则表达式)
- 从零开始学_JavaScript_系列(30)——NodeList
- 从零开始学_JavaScript_系列(32)——事件广播
- 从零开始学_JavaScript_系列(43)——Symbol简述
- 从零开始学_JavaScript_系列(47)——Reflect
- 从零开始学_JavaScript_系列(15)——js系列<3>(转为字符串,截取字符串)
- 从零开始学_JavaScript_系列(64)——class的继承(1)基本概念、继承构造函数和class
- 从零开始学_JavaScript_系列(19)——js系列<6>闭包
- 从零开始学_JavaScript_系列(十)——dojo(3)(GRID表格创建、样式、列宽可变、排序、过滤器)
- 从零开始学_JavaScript_系列(16)——CSS<3>(文本、对齐、圆角、盒模型、背景)
- MyBatis(2)--MyBatis标准示例(单例)
- [BZOJ2434][NOI2011]阿狸的打字机-AC自动机
- python运维first_chapter
- You Don't Know JS: Types & Grammar 总结
- javascript学习记录(二)-function函数的应用之sort()函数详解
- 从零开始学_JavaScript_系列(55)——Generator函数(3)yield*表达式
- 响应式布局学习
- malloc1
- 从零开始学_JavaScript_系列(56)——Generator函数(4)简写,this与继承
- HDU 6166 Senior Pan [二分+SPFA]
- 《运营之光》-- 学习笔记(一)
- Hdu 4389 X mod f(x) 数位DP
- 从零开始学_JavaScript_系列(57)——Generator函数(5)状态机与函数的应用
- solr6.6.0安装部署至tomcat教程