Generator
概念
1)函数声明方式:在function关键字与函数名之间有个 * 号
2)函数体内:可以使用yield表达式
3)执行时:返回一个iterator对象,可以用过调用next方法,遍历iterator对象里的每个yield表达式定义的状态
yield表达式
1 | function *test(){ |
并没有打印出 1
1 | function *test(){ |
未打印出 2
1 | function *test(){ |
yield表达式特点:
1)调用Generator函数并不会马上执行,而是返回一个Iterator对象。
2)在Generator函数体内,yield可以有多个,并且yield会暂停函数执行。
3)通过yield定义内部状态
next方法
通过上面的了解,调用Generator函数会返回一个Iterator对象,而不会马上执行函数。
1)调用Iterator对象的next方法,就会从函数体头部开始执行,到第一个yield后结束。再次调用next方法的时候会从中断的地方继续往下执行。
2)调用next方法会返回一个包含value和done的对象,value的值就是yield后面跟随的值。
3)调用next之后会一直往下执行,如果遇到yield就被暂停,如果遇到return,就将return后面跟的值作为返回对象的value的值。
4)如果没有return语句,那么返回的值是undefined。
1 | function *test(){ |
1 | function *test(){ |
1 | function *test(){ |
从上面得知,返回值会有3种,分别是:
1)yield后的值
2)return的值
3)undefined
并且yield是没有返回值的
next方法的参数
而next方法传递的参数,该参数会被当成yield的返回值
1 | function *test(){ |
通过对上面的调用的观察:
1)第一次调用next传入的参数是无效的。
2)next方法的参数被当成上一个yield的返回值。
3)使用next方法遍历Iterator里的所有状态的次数,会比yield的个数多一次,因为第一次是启动。
yield*
在一个Generator函数里调用另外一个Generator函数
1 | function *test(){ |
发现并无卵用,没能在yield 1
的地方停止执行
使用yield*
1 | function *test(){ |
那么问题来了,怎么取得test函数里的返回值
1 | function *test(){ |
yield*
与for...of
1 | function *test(){ |
再看yield
与yield*
1 | function *test(){ |
可以看到yield test()
返回的是一个Iterator对象
另外,只要有Iterator的数据类型都可以使用yield*
1 | var arr = [1,2,3]; |
另外可以使用yield*
,将多维数组扁平化
Generator函数与Iterator
1 | var obj = { |
因为对象是没有Iterator
接口的,可以将Generator函数赋值给对象的Symbol.iterator
,这样就让对象获得了Iterator接口。
1 | var obj = { |
稍微看一下具有Iterator
接口的数据类型
1 | //数组 |
对有Iterator接口的数据类型,可以使用展开运算符
,解构赋值
,for…of
,Array.from
。了解一下字符串反转)