es6-yield关键字的学习

~~~~~今天看前端代码的时候,看到很多yield关键字,所以就来学习下yield是什么~~~~~~~~

The yield keyword is used to pause and resume a generator function.
// yield这个关键字是用来暂停和恢复一个遍历器函数(的运行)的

所以可以看出来,es6的yield跟python中的yield关键字用法是非常类似的,如果了解python的生成器,那么这篇就很好理解了。。。

#语法
[rv] = yield [expression];

遍历器函数Generator

Generator 函数有多种理解角度。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。
执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。

function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();

上面代码定义了一个 Generator 函数helloWorldGenerator,它内部有两个yield表达式(hello和world),即该函数有三个状态:hello,world 和 return 语句(结束执行)
Generator 是啥
#遍历器函数语法
function *foo(){
  ...
  [rv] = yield [expression];
  ...
}

所以yield是跟generator一起使用的,现在我们来看下如何用

var a=0;
function *foo(){
a+=1;
yield a;
}
var f=foo();
alert a;

浏览器控制台执行下,结果是0,证明并没有执行foo()内的代码。原因是调用生成器函数只是生成一个遍历器对象。要想执行,必须是next()方法

代码更改如下:

var a=0;
function *foo(){
a+=1;
yield a;
}
var f=foo();
f.next();
alert(a);

再次执行,弹框是1,证明执行了foo函数。

每次执行next(),都是循环一次函数体,我们看下执行的过程

我们看到上面执行的yield返回结果是一个value,一个done值,done表示的就是是否遍历完成。false就是没遍历完成,true是遍历结束。
当 运行到yield的时候,程序暂停了,不会继续执行。而当遇到return的时候,表示遍历结束,看下面的两个例子

特点:
所以生成器跟普通函数的区别是,你需要跟他要值,他才给。要一个给一个,给完了,他就没有了。或者一下子要过来,他就变空了。
var a = 0;
function *foo() {
  a += 1;
  yield '';
  return;
}
var f = foo();
#执行下面的代码
var s1 = f.next(); 
console.log(s1); // {value: '',done: false}yield返回的是空字符串,所以value是空字符串,然后遍历暂停,不会执行return。
var s2 = f.next();
console.log(s2); // {value: undefined,done: true} 第一次暂停后,继续往下执行return,但是return返回的是空,所以value是undefined。一旦return,遍历即结束,所以done为true
var a = 0;
function *foo() {
a += 1;
yield a;
a+=3;
return a;
}
var f = foo();
s1=f.next();
console.log(s1);
// {value: 1,done: false}
s2=f.next();
console.log(s2); // {value: 4,done: true}

那接下来,我们来学习下.next()的参数,没错,next()函数可以传参。

看下我从别处拉来的几行代码

var foo = function *() { // 没错,尼玛还可以这样写
  var x = 1;
  var y =  yield (x + 1);
  var z = yield (x + y);
  return z;
}() // 你必须先执行一下Generator函数,才能把遍历器返回给某个变量
var a = foo.next(); // 第一次执行next()不可以传参
var b = foo.next(3);
var c = foo.next(4);

求abc的值?
a显而易见,就是返回的(x+1)=2
b为foo.next(3),这个3是啥意思,是传给上一个yield的值,这时可以把yield当做一个参数。也就是说y被赋值3,b为(x+y)=4

foo.next(4),就是把4赋值给了上一个yield值即z,所以c就是最后return的值4。

OK,相信你已经看懂了,那再看看下一段代码:

var log = function *() {
 a=yield 1;  console.log(`you input: ${a}`) }();
log.next();
log.next('hello world!');
结果:Object { value: undefined, done: true

结果:
you input: hello world!
Object { value: undefined, done: true },
原因:1. log.next() 执行到yield 1结束。注意,这时的a并不是1。
2. log.next('hello world!') 执行,会把‘hello world!’ 赋值给参数a,从上次yield语句后开始执行,所以会打印出--》you input: hello world!
3. undefined,是因为已经没有yield了,所以undefined

var log = function *() {
 a=yield 1; 
  console.log(`you input: ${a}`)
}();
log.next();
log.next();#不传参数的话,a相当于没有赋值,会报undefined。所以如果想用a,必须传参

结果:

you input: undefined
{value: undefined, done: true}

 

总结一下

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

  • 只能在Generator函数内部使用
  • 运行.next(),遇到一个yield命令,就暂停
  • .next()的返回值表示一个状态{value,done}
  • 再运行.next(),从之前遇到的那个yield [表达式]处(后)继续恢复运行
  • 当.next()传参的时候,yield [表达式]整个被替换为传入的参数。
 

 

转载于:https://www.cnblogs.com/lixiaoxuan/articles/10243976.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值