您的位置 首页 > 德语词汇

yield是什么意思?用法、例句(代码写了那么多,你搞明白yield是个啥没?)

本篇文章给大家谈谈yield是什么意思?用法、例句,以及代码写了那么多,你搞明白yield是个啥没?对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。

yield是什么意思?用法、例句(代码写了那么多,你搞明白yield是个啥没?)

代码写了那么多,你搞明白yield是个啥没?

ES6真是颠覆JavaScript的东西,随便翻一个新特性出来,就让自以为是的老古董们傻眼跳楼。在之前接触ember.js的时候,接触到了yield,嫩是半天没明白,yield到底是什么,想要实现什么目的。后来在看ES6的东西的时候,总算好像知道了一点,迫不及待的写出来。

在MDN上,对yield的第一句解释就是:

Theyieldkeywordisusedtopauseandresumeageneratorfunction.//yield这个关键字是用来暂停和恢复一个遍历器函数(的运行)的。

这也就是yield的所有解释了,可谓大道至简,然并卵,深层的意思不去挖掘,根本还是没法用它,还是老老实实做老古董。

没错,yield是个关键字,不是函数。关键字用来干啥?它的作用是“命令”。和var不同,不是用来声明,但是和return一样,用来告知程序某种状态,return告诉程序要返回什么值(也意味着结束,结束的时候才会返回值嘛),而yield告诉程序当前的状态值,而且你运行到这里给我暂停一下。

因为yield是命令型的关键字,所以它的用法是:

[rv]=yield[expression];

rv是可选的,这里不是说它返回一个数组。yield后面的表达式也是可选的。yield的返回值是一个状态值。如果从返回值的角度讲,yield还可以当做是一种运算符,但是由于它的作用是暂停和恢复,所以严格意义上说,不能叫运算符,运算符是用来运算的,而yield是用来“命令”的。

这是ES6里面新增的Generator,为了把它和我们已知的东西联系起来,我把它翻译为迭代器函数,但是实际上现在还没有统一的叫法,坐等大神们开宗立派。

我个人的理解,Generator函数的最大用处就是用来生成一个迭代器,所以叫做“迭代器生成器”。

不过它是一个函数,所以和普通的函数有点区别,因此在声明函数的时候,要在function和函数名之间加一个*号:

而yield也必须在Generator函数中才有意义,脱离了Generator函数就没意义了。

Generator函数的一个重要特点就是需要执行next()方法才能运行,声明好它之后,根本不会马上运行。举个栗子:

上面的例子如此简单,你不会看不懂吧?现在告诉你,alert的结果是0!

我前面都说了,要执行netx()方法才会运行。所以在上面的代码末尾添加:

alert(a)//这个时候就会alert(1)了

就用上面的代码来说好了。Generator函数生成的是一个迭代器,所谓迭代器,你不让它动,它绝对不会动。

不要用“动”这么猥琐的词好吗?

“执行、运行”,i作为一个迭代器,最基本的的特征是它拥有一个next方法和一个当前的状态。当调用i.next()的时候,程序从generator函数开始运行,当遇到yield命令时,就“暂停”刮起,并且返回yield[expression]的expression的运算结果,这个结果就是前文所讲的“状态”

比如程序在往下运行的时候,遇到yield1+2,那么i.next()返回的结果就是这个时候的状态,是一个对象,其运算结果“3”被放在value中。

i.next()就是让它往下一个元素遍历的动作,它的返回值其实表示一个状态,是一个object:{value:xxx,done:false}。value表示yield后面的表达式的结果值,done表示是否已经遍历完。把上面的i.next()那段代码改成下面的:

console.log(s1)//{value:'',done:false}

console.log(s2)//{value:undefined,done:true}

第一个console的地方,因为第一次执行i.next(),遇到yield就暂停了,并讲yield后面的表达式作为值放到状态的value属性上。得到s1这个状态,这个状态的value是yield后面紧跟的表达式的值,done表示遍历没有结束,还可以继续执行next()方法。第二次再执行i.next()的时候,遇到了return,但后面没有表达式,所以返回值是undefined,一旦遇到return就表示遍历可以结束了,所以done为true。

当运行到yield'';的时候,程序暂停了,不会往下继续执行,所以下面的各种加减乘除都不会运行,这也就是为什么我们上面的代码在运行i.next()之前,虽然执行了foo()这个函数,但是a的值是0,就是因为还没有执行i.next(),所以yield前面的a+=1还没有运行。

也正是因为有.next()方法,所以它叫迭代器。for...of,...,Array.from都是利用迭代器接口进行运算的,所以如果没有Generator,这几个方法就用不了。而在Babel里面,babel-core本身不支持Generator,所以这几个运算其实也需要另外的模块(regenerator)来支持。

一不小心讲到了babel,罪过罪过。

造孽的地方终于要来了。一言不合,就上代码:

constgen=function*(){//没错,尼玛还可以这样写

}constfoo=gen()//你必须先执行一下Generator函数,才能把遍历器返回给某个变量consta=foo.next()//第一次执行next()不可以传参,就算传参也没有效果

constb=foo.next(3)//后续的next都可以传参

你要没接触过,这个时候只会冒出来“吊雷老某”……a.value你应该知道,就2(x=1,x+1=2)。b.value呢?傻戳戳了吧。

.next()的参数的意思是将传入的参数用作上一次的yield。啥子意思?就是第二次执行foo.next(3)的时候,yield(x+1)这一大坨就是3,所以y=3!“xx老谋”。所以,b.value的结果就是4(x=1,y=3,x+y=4).

这样推下去咯。最后返回的是z,但是传入的是4,yield(x+y)这一大坨就用4来代替,z.value=yield(x+y)=4。

为什么第一次执行next()不能传参?

因为第一次执行next()的时候,你传入的参数没法去代替某一个yield啊!

这里我们规定y=(yieldx+1)+2,意味着当next(5)的时候,(yieldx+1)会被整个替换掉,y=5+2=7。

总结一下,想知道迭代器当前的状态值,也就是.next()的返回值,只需要看yield后面的表达式的结果。但是由于大部分情况下,yield后面的表达式由前面的运算结果参与,所以,处于后面的yield的值,要看前面的yield接收到的next()的参数,带入赋值并运算之后才能知道状态的值。

上面这一个小节你有没有发现一个神奇的规律?就是你在给next()传参的时候,总是对应某一个yield,把这个yield以及后面紧跟着的表达式用传入的参数代替。于是乎,下面这个代码你就懂了:

上面这个代码里面,竟然把yield后面的表达式给去掉了。那会有啥影响?b.value将等于undefined,仅此而已。因为b这个位置就是得到yield[空]的结果,所以就是undefined咯。但是当foo.next(4)执行的时候,不管你上面是不是undefined,我现在就是要用4来覆盖你,所以c.value还是4.

也正因为这样,在字符串里面,可以这样使用:

console.log(`youinput:${yeild}`)

}().next();//这里会提示错误:yeildundefinedlog.next('helloworld!');

上面这个例子把yield当做一个变量来使用,如果你感兴趣,可以想办法吧第一次的时候错误去除掉。

这个用法看上去很挫,但是很厉害的是,可以通过这个思路,实现字符串模板的次第渲染。可以控制渲染到哪个位置。

写了这么多,总结一下yield,实际上:

2.运行.next(),遇到一个yield命令,就暂停

3..next()的返回值表示一个状态{value,done}

4.再运行.next(),从之前遇到的那个yield[表达式]处(后)继续恢复运行

5.当.next()传参的时候,yield[表达式]整个被替换为传入的参数。

最后,说一下for...of是怎么运行的。

for...of在遍历foo()返回的结果时,每遇到一个yield,就把yield后面表达式的结果作为of前面的v的值进行赋值(next()返回值的value字段)。没错,就这么不要脸的解释完了。

我发现了一个错误(不确定是不是文章中的错,或者是我和博主用的js环境不一样,我用的Edge87.0.664.47控制台),错误位置在这:↓https://www.tangshuang.net/2862.html#把yield当变量看(上一行)(没法贴图

但是,经过我的实验,发现yield会将后面跟的一整行表达式全部当成一坨(不加括号的话)↓“`javascriptvarfoo=function*(){varx=1;vary=yield(x+1);varz=yieldx+y;returnz;}()foo.next()//{value:2,done:false}foo.next(3)//{value:4,done:false}

而且,我发现,next()中传参数的话,上一个yield的结果是被永久替换的,这一点算是补充吧↓“`javascriptvarfoo=function*(){varx=1;vary=yield(x+1);varz=(yield2)+y+2+2+y;returnz;}()foo.next()//{value:2,done:false}foo.next(3)//{value:2,done:false}foo.next(4)//{value:14,done:true}

关于yield是什么意思?用法、例句到此分享完毕,希望能帮助到您。

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023