JavaScript:生成器函数
创始人
2024-02-03 10:43:23

在介绍生成器函数之前先了解一下ES6的一个关键字,名为yield

yield关键字,可以让代码在其出现的地方暂停执行,它只能在生成器函数内部使用。

生成器函数

生成器函数的语法比较简单在普通函数声明的时候在函数名前面添加一个*即可,如下所示:

function *gen(){}

当函数被调用时会返回一个返回值,但是生成器函数与普通函数的返回值有些区别。

普通函数如果没有使用return返回时,接收到的是undefined,而生成器函数不管有没有return都返回一个对象,这个对象被称为迭代器,我们可以通过这个对象控制迭代器的执行。通常,使用迭代器的next方法,让其继续执行。

let x = 0;
function *gen(){console.log(x);yield x++;
}
let itr = gen();
console.log(itr)

在这里插入图片描述

根据上面的结果我们可以知道,生成器函数在被调用时并不会开始执行代码。得到了一个对象,这也验证了上文所言。
接下来,我们让它继续执行,需要调用next方法。

let x = 0;
function *gen(){console.log(x);yield x++;
}
let itr = gen();
console.log(itr)
itr.next();
console.log(x)

在这里插入图片描述
从上面的结果来看,next方法也验证了前文所言。
当我们调用next方法时,next方法也会返回一个对象,这个对象包含一个value属性,value属性的值是当前yield语句的结果。

let x = 0;
function *gen(){console.log(x);yield x++;
}
let itr = gen();
console.log(itr)
let res = itr.next();
console.log(res)

在这里插入图片描述
我们根据结果可以看到,除了value属性,还可以看到一个done属性,done属性的值表示迭代器的完成状态,为true表明完成迭代,为false,表明没有完成迭代。

如果一个生成器函数中使用return,我们需要得到return的值,这时候需要使用next方法返回的对象的value属性得到返回的值。

let x = 0;
function *gen(){console.log(x);yield x++;return x;
}
let itr = gen();
let res = itr.next();
console.log(res.value);
res = itr.next();
console.log(res.value,res);
res = itr.next();
console.log(res);

在这里插入图片描述
根据输出的第三行,我们可以看到输出的值是1,与预想的一样,同时done属性也为true,说明运行到return语句。当我们再次运行next方法时,此时函数已经执行完毕,不在执行,也就没有返回值,因此是undefined。

但是在返回1之前,还有一个值,这个值是yield x++; 语句的返回值,x++的返回值是0,因此value属性是0

这样一个完整的迭代器运行流程我们就了解了。

接下来,我们再了解一下next方法。之前我们知道next方法返回一个对象,可以通过value属性得到返回值。

next方法也可以接收一个值

let x = 0;
function *gen(){console.log(yield);x++;return x;
}
let itr = gen();
let res = itr.next(6);
console.log(res);
res = itr.next(7);
console.log(res);

在这里插入图片描述
根据结果我们可以知道,第一个next传递参数并不会被接收,规范和所有兼容浏览器都会默默丢弃传递给第一个next()的任何东西。传值过去仍然不是一个好思路,因为你创建了沉默的无效代码,这会让人迷惑。因此,启动生成器时一定要用不带参数的next()。

只有从第二个next开始传递的参数才会被接收,由此,我们可以总结,next传递的值被上一个yield接收,next与field相差一个间隔。

那么为什么会产生这个差距呢?

因为第一个next(…)总是启动一个生成器,并运行到第一个yield处。不过,是第二个next(…)调用完成第一个被暂停的yield表达式,第三个next(…)调用完成第二个yield,以此类推。

以上就是生成器函数的基本使用,那么生成器函数到底有什么用或者说能够应用在什么场景呢?

生成器函数可以应用在异步任务中,当一个异步任务没有返回值时我们可以让程序在此处暂停当有返回值时在调用next继续执行。

示例

        function run(gen) {var args = [].slice.call(arguments, 1), it;// 在当前上下文中初始化生成器it = gen.apply(this, args);// 返回一个promise用于生成器完成return Promise.resolve().then(function handleNext(value) {// 对下一个yield出的值运行var next = it.next(value);return (function handleResult(next) {// 生成器运行完毕了吗?if (next.done) {return next.value;}// 否则继续运行else {return Promise.resolve(next.value).then(// 成功就恢复异步循环,把决议的值发回生成器handleNext,// 如果value是被拒绝的promise,// 就把错误传回生成器进行出错处理function handleErr(err) {return Promise.resolve(it.throw(err)).then(handleResult);});}})(next);});
}

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...