Generator函数

重要概念

1.Generator函数执行后,函数并不会主动往下执行任意一个字符,而是返回一个指向内部状态的指针对象,是一个遍历器对象(Iterator Object)

2.想要函数继续执行,必须要在函数执行时返回的对象上调用next()方法:

注意:

在调用next()后,函数会一直执行到包含yield的表达式,此时,在这个表达式中,会首先执行yield后的表达式(子表达式),并将其作为next函数执行后返回对象的value属性的值,此时函数就暂停执行了,而不再执行父表达式。

上述函数暂停执行的地方,使得Generator函数执行返回的Iterator对象中的next()方法的参数存在有意义。本次调用x.next(arg),这里的arg将会作为上一次yield表达式的返回值,并继续执行上一次yield表达式的父表达式(如果父表达式存在的话)直到下一个yield或者函数结束。

若next()不带参数,则yield返回undefined:

function *gen(x){
    let result = yield x;
    console.log('result: ' + result );
}

let g = gen(5);
g.next();//{value: 5, done: false}
g.next();//result: undefined
         //{value: undefined, done: true}

这里的上一次也包含着:

由于next方法的参数表示上一个yield表达式的返回值,所以在第一次使用next方法时,传递参数是无效的。V8 引擎直接忽略第一次使用next方法时的参数,只有从第二次使用next方法开始,参数才是有效的。

3.函数的返回值会作为最后一次调用next方法返回的对象中value属性的值。{value: 函数返回值, done: true}

 

Generator.prototype.next():

Generator.prototype.return():

Generator.prototype.throw():

next()throw()return()这三个方法本质上是同一件事,可以放在一起理解。它们的作用都是让 Generator 函数恢复执行,并且使用不同的语句替换yield表达式。以上均可查阅参考1

Generator的this

generator函数不能作为构造函数,即不能通过new关键字实例化,但generator函数执行会返回迭代器,这个迭代器规定是generator函数的实例,因此会继承generator的prototype属性。

function *gen(){}

gen.prototype.test = function() {
    console.log('yes');
}

let tmp = gen();

tmp.test();//yes

既然generator函数不能通过new实例化,而且执行也是返回迭代器,那么在generator函数中通过this关键字定义的属性,通过generator返回的迭代器实例是无法访问到的。

function *gen(){
    this.a = 5;
    yield 5;
}

let tmp = gen();
tmp.next();//{ value: 5, done: false }
tmp.next();//{ value: undefined, done: true }
tmp.a;//undefined

让generator函数执行返回的迭代器实例,表现为generator函数通过new关键字创建实例的行为(也就是返回的迭代器对象能够访问generator函数中this定义的属性):

//这里把tmp对象绑定到了foo函数中this关键字上
//因此访问a时,要通过tmp对象去访问
//注意这里的两次调用next方法,只有generator函数执行到指定代码时,相应的操作才会生效

//不过这里是绑定到了tmp对象上,而非绑定到generator函数执行返回的迭代器实例上
function *foo(){
    yield 1+1;
    this.a = 'yes';
}

let tmp = {};
let s = foo.call(tmp);

s.next();//...
s.next();//...

s.a//undefined
tmp.a//yes

改进版:

//将generator函数中this绑定到generator的prototype属性上
//此时属性就定义到了prototype上

function *foo(){
    yield 1 + 1;
    this.a = 'yes';
}

let s = foo.call(foo.prototype);

s.next();
s.next();

s.a//yes

 

tips

Generator函数本身就可以保存状态,因此可以避免常规函数实现状态机时定义状态变量。

参考:

[1].http://es6.ruanyifeng.com

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值