yield的使用

学习yield这块的时候发现别人的博客写的不太清楚 所以自己写了个try.html试了下

Generator 函数
Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。

一个Generator函数与普通function的区别就是函数名前面多了一个星号 * 但是执行时有很大不同,与yield命令配合,可以实现暂停执行的功能

//公司代码风格没有分号,正在适应,不喜勿喷
let go = function*(x) {
console.log(‘x’, x)
let a = yield x
console.log(‘xx’, x)

console.log('a', a)

let b = yield x + 1

sum = a + b

yield a + b

return a + b

}
go(10)
//let g = go(10)
// console.log(g.next())
// console.log(g.next(1000).value)
// console.log(g.next(50).value)
// console.log(g.next().value)
1

上面代码打了很多log,用来发现generator函数和yield的执行方式,很原始但是很有效

如上,只执行了

go(10)

这一行代码,发现console是空的,所以说明 generator 函数被直接执行时是没有执行函数体内的代码的,否则应该执行 console.log(‘x’, x) ,要让代码执行,需要通过 next() 函数

修改代码如下

let go = function*(x) {
  console.log('x', x)
  let a = yield x
  console.log('xx', x)

  console.log('a', a)

  let b = yield x + 1

  sum = a + b

  yield a + b

  return a + b
}
go(10)

let g = go(10)
console.log(g.next())
// console.log(g.next(1000).value)
// console.log(g.next(50).value)
// console.log(g.next().value)

1

只是去掉了一行注释, 运行了 console.log(g.next().value) 这一行

结果为

x 10
Object {value: 10, done: false}
1
2
原来只有在调用了 next() 函数之后,函数才会开始执行,但是结果中没有看到打印的 xx 字样,所以应该是代码运行停在了 let a = yield x 这一行,所以 Object {value: 10, done: false} 就是yield的返回值,这个功能类似return 但是也有区别。

文档说,yield的返回是一个对象,包括 value 和 done 两部分,value自然是返回值,done是该generator函数是否执行完,这里看到false,就是表明该函数还有后续可以执行的部分。

再去掉一行注释,为了方便我把整个代码贴上

let go = function*(x) {
console.log(‘x’, x)
let a = yield x
console.log(‘xx’, x)

  console.log('a', a)

  let b = yield x + 1

  sum = a + b

  yield a + b

  return a + b
}
go(10)

let g = go(10)
console.log(g.next())
console.log(g.next(1000).value)
// console.log(g.next(50).value)
// console.log(g.next().value)

1
2

结果也贴上

x 10
Object {value: 10, done: false}
//以下是新出现的结果
xx 10
a 1000
11
1
2
3
4
5
6
首先看到了xx开头的log,表明代码是从刚才yield的地方开始执行的,然后注意,代码中有刚才第一个yield是这么写的

let a = yield x
console.log(‘xx’, x)
console.log(‘a’, a)
1
2
3
在yield之后是两个log,一个是xx上一步用来辨别代码执行到了哪里,另一个a的值,是刚才从yield获取的 let a = yield x ,从结果来看,a是1000,这和我第二次调用next()时所用的参数值是一样的。

根据赋值语句的执行顺序,let a = b + c 会先计算 b + c 的值,然后在做赋值操作,同理

第一次调用next() 时,yield 把 x 的值 扔到了外面作为next()的返回值,赋值语句本身并没有来得及执行就暂停了,所以当第二次next() 函数调用时,函数是从赋值语句开始的,第二次的next()的参数1000,也作为原yield关键字的值传递给了a,所以才会看到结果中的 a 1000

如果没有这个1000,a是什么呢?

a undefined

所以,next()如果没有参数,当generator继续执行时,上次跳出所用的yield将是undefined

这次来看看generator的结束

let go = function*(x) {
  console.log('x', x)
  let a = yield x
  console.log('xx', x)

  console.log('a', a)

  let b = yield x + 1

  sum = a + b

  yield sum

  return sum
}
go(10)

let g = go(10)
console.log(g.next())
console.log(g.next().value)

//这里加了三个
console.log(g.next(50))
console.log(g.next(8))
console.log(g.next(8))
1
2

结果

x 10
Object {value: 10, done: false}
xx 10
a 1000
11
//本次增加的log
Object {value: 1050, done: false}
{value: 1050, done: true}
{value: undefined, done: true}
1
2
3
4
5
6
7
8
9
可以推测出,这次传入的50,是赋值给了b,然后sum = a + b 自然是1050,代码运行停止在了yield sum,返回1050,

后一次调用next(),虽然传入了8,但是没有被接收,所以没有什么用,程序执行到了return,

返回的结果自然还是1050,但是由于generator 结束了,next()方法的返回值中的done 也变成了true,表示没有下一个next()可以操作了。当然如果用了,也不会报错,只是如结果所示,因为已经找不到什么可以执行的代码了,所以只能是undefined,同时done 的值还是true

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值