「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」 摘要:本文主要写了javascript中的生成器函数概念,语法及与默认迭代器直接的关系,还有yield的使用,各部分附有示例代码参考。
1.生成器的概念及语法
生成器的形式是一个函数,语法为在function和函数名之间有一个*号,在函数体中可以使用yield关键字去暂停函数的执行。调用该函数将返回一个生成器对象,该生成器对象实现了iterator接口,所以,该生成器也是一个迭代器,有next()方法去遍历 开始运行整个函数体,遇到yield时暂停执行,再次调用next时,从函数上次中止的地方接着运行,以此类推,直到函数体结束。 参考代码如下,其中g1为生成器函数,it1为调用该生成器函数产生的迭代器:
function* g1(){
console.log("第一次yield");
yield;
console.log("第二次yield");
yield;
}
let it1 = g1();
console.log(it1.next());
console.log(it1.next());
console.log(it1.next());
/*输出结果如下:
第一次yield //第一次调用next()方法是函数开始执行,打印出此行
{ value: undefined, done: false } //此打印为调用next()的返回值iteratorResult对象
第二次yield //第二次调用next()方法是函数继续执行,打印出此行
{ value: undefined, done: false } //此打印为调用next()的返回值iteratorResult对象
{ value: undefined, done: true } //此打印为调用next()方法,函数已运行完,所以done的value为true
*/
2.用生成器函数给对象自定义默认迭代器
从迭代器那节我们知道,调用对象的Sympol.iterator工厂函数,会返回一个迭代器对象,所以我们也可以给这个工厂函数 声明为一个生成器函数,用来实现自定义默认迭代器,实例代码如下,实现功能和上篇博客的自定义默认迭代器一样,生成10个 1-10直接的随机数:
class RandomValue{
constructor(number,max){
this.number = number;
this.max = max;
}
*[Symbol.iterator](){
let count = 1;
let number = this.number;
let max = this.max;
while(count<=number){
yield Math.floor(Math.random()*max)+1;
count++;
}
}
};
let r1 = new RandomValue(10,10);
let a1 = new Array();
it1 = r1[Symbol.iterator]();
for (const i of it1) {
a1.push(i);
}
console.log(a1);
/*输出结果为:
[
4, 3, 4, 4, 10,
10, 5, 9, 8, 9
]
*/
3.yield的使用
3.1 yield用来暂停函数的运行,但yield后面可以加表达式作为调用next时返回的value值,不加时则为undefined(从上面的代码结果 可以看到)。所以,yield可以看作是函数的中间返回值。函数暂停时,其作用域会保留。运行的函数结尾时,可使用return来控制返回的value值。上述各点参考代码如下:
function* g2(){
yield "first";
yield 3+7;
return "end";
}
let it2 = g2();
console.log(it2.next());
console.log(it2.next());
console.log(it2.next());
/*输出结果如下:
{ value: 'first', done: false } //value为第一个yield后面的值
{ value: 10, done: false } //value为第二个yield后面的值
{ value: 'end', done: true } //value为return后面的值
*/
3.2 yield后面也可以加*来遍历它后面所跟的迭代器(或者说可迭代对象),如内置类型数组,依次返回数组中的值。也可为生成器函数的调用,即一个生成器函数里可以调用另外一个生成器函数,其中的一个特殊现象就是调用这个生成器函数 本身即递归。参考代码如下,实现功能计数为10,每next一次,计数减一。
function* g3(n){
if(n>0){
yield* g3(n-1);
yield n;
}
}
let it2 = g3(10);
let a3 = new Array();
for (const i of it2) {
a3.push(i);
}
console.log(a3);
/*输出结果为:
[
1, 2, 3, 4, 5,
6, 7, 8, 9, 10
]
*/