js yield和Generator 函数

学习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)

上面代码打了很多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)

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

结果为

x 10
Object {value: 10, done: false}

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

文档说,yield的返回是一个对象,包括 valuedone 两部分,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)

结果也贴上

x 10
Object {value: 10, done: false}
//以下是新出现的结果
xx 10
a 1000
11

首先看到了xx开头的log,表明代码是从刚才yield的地方开始执行的,然后注意,代码中有刚才第一个yield是这么写的

let a = yield x
console.log('xx', x)
console.log('a', a)

在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))

结果

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}

可以推测出,这次传入的50,是赋值给了b,然后sum = a + b 自然是1050,代码运行停止在了yield sum,返回1050,

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

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

仅以本文作为笔记方便自己以后忘记时理解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值