前言
很早之前就了解过一点,但日常开发基本都见不到它的身影。今天带大家再学习一遍 function* ,了解一下它的可用场景。
什么是生成器函数
function* 这种声明方式会定义一个生成器函数 (generator function),它返回一个 Generator 对象。
示例:
function* test() {}
生成器函数的特点:
- 调用生成器函数,并不会马上执行它里面的语句,而是返回一个
Generator对象(是一个可迭代对象)。 - 生成器函数在执行时能暂停,后面又能从暂停处继续执行。
- 调用
Generator对象的next()方法,代码会执行到下一个yield语句处并暂停执行,然后返回yield表达式的值。
Tip
我们可以从两方面来使用生成器函数。
- 利用它返回的可迭代的
Generator对象- 通过无限循环和
yield,调用next()来生成你想要的数据
使用场景
-
利用它返回的可迭代的
Generator对象,来展平数组function* iterArr(arr) { //迭代器返回一个迭代器对象 if (Array.isArray(arr)) { // 内节点 for(let i=0; i < arr.length; i++) { yield* iterArr(arr[i]); // (*) 递归 } } else { // 离开 yield arr; } }Generator对象是可迭代对象,它的迭代元素是由yield返回值组成的。再看上述代码,当arr不会数组时,使用yield组装到可迭代对象上;反之,继续交给生成器函数去执行。遍历这个
Generator对象var arr = ['a', ['b', 'c'], ['d', 'e']]; for(var x of iterArr(arr)) { console.log(x); // a b c d e } // 或者将迭代器展开 var gen = iterArr(arr); arr = [...gen]; // ["a", "b", "c", "d", "e"]使用递归算法时,我们经常使用
return来组装我们想要的结果,现在使用 生成器函数 也是可以的。上述代码普通函数实现:
var arr = ["a", ["b", "c"], ["d", "e"]]; function iterArr(arr) { let acc = [] if (Array.isArray(arr)) { arr.forEach((item) => { // 这里是最终的结果 acc = [...acc, ...iterArr(item)]; }); } else { // 递归调用的返回值,用来组装最终的结果 acc = [...acc, arr]; } return acc; } console.log(iterArr(arr)) // [ 'a', 'b', 'c', 'd', 'e' ]显然,这里普通函数没有生成器函数用起来方便。
-
用生成器函数返回随机数
function* getRandom(num) { while(true) { yield (Math.random() * num).toFixed(0) } } const getRandomGen = getRandom(10) console.log(getRandomGen.next().value) console.log(getRandomGen.next().value)当然用普通函数获取随机数也很容易,此处只为举例。
Tip
生成器函数可以传参,有
arguments
总结
- 生成器函数做一个了解就行,毕竟使用场景不多。