ES6—Genterator函数

一、Genter函数:

function命令和函数名之间有一个星号(ES6没有规定星号写在哪个位置 只要在function和函数名之间即可)
函数体内部使用yield语句定义不同的内部状态
调用genterator函数后返回一个指针对象,是一个遍历器对象,每次调用该遍历器对象的next方法,内部指针就上一次执行的地方开始,到当前yield语句为止

  • yield语句是暂停标志,不能写在普通函数中,否则会报错,即使是在generator里的普通函数
  • yield如果在一个表达式中,必须放在圆括号里
  • next方法可以带参数,表示上一条yield语句的返回值

二、Genterator的for…of循环

一旦next方法的返回对象的done属性为true,for…of循环就会众智,且不包含该返回对象,所以return的内容不会获取到。

三、Genterator.prototype.throw()

每个Genternator对象有一个throw方法,可以在函数体外抛出错误,在Genterator函数体内捕获。

var g = function* () {
    while (true) {
        try {
            yield; 
        } catch (e) {
            if (e != 'a') throw e;
            console.log('内部捕获', e);
        }
    }
};

var i = g();
i.next();
try {
    i.throw('a');
    i.throw('b');
} catch (e) {
    console.log('外部捕获', e);
}
// 打印内容:
// 内部捕获 a
// 外部捕获 b

上面代码中,遍历器对象i连续抛出两个错误。第一个错误被Genterator函数体内的catch语句捕获,然后Genterator函数执行完成,第二个错误被函数体外的catch语句捕获。

  • 如果不是使用遍历器对象的throw方法抛出,而是使用throw命令的话,只能在函数体外的catch语句中捕获。
  • 如果Generator函数内部部署了try…catch代码块,遍历器throw方法抛出的错误不会影响下一次遍历,否则下一次遍历会终止
  • Genterator函数定义的内部出现错误也可以被函数外部捕获,出现错误之后,遍历器不会继续执行下去,此后还调用next方法,将返回一个value属性等于undefined,done属性等于true的对象。

四、Genterator.prototype.return()

Genterator函数返回的遍历器对象有return方法,可以返回给定的值,并结束Genterator函数的遍历,如果return方法调用时不提供参数,则返回值的value为undefined。

function* gen() {
    yield 1;
    yield 2;
    yield 3;
}

var g = gen();
g.next(); // { value: 1, done: false}
g.return("foo");  // { value: "foo", done: true}
g.next();  // { value: undefined, done: true}

五、yield*语句

在Genterator函数内部调用另一个Genterator函数,默认情况下没有效果。
如 foo函数、bar函数,在bar函数中调用foo函数不能将bar函数里面的元素添加到foo函数中。
但是可以通过yield* foo()完成调用 如果不添加也即 yield foo()的话,调用的时候返回一个遍历器对象,任何数据只要有Iterator接口,就可以使用yield遍历。

六、Genterator函数的this

Genterator函数中是不能直接通过This对象增加属性的。

function* g() {
    this.a = 11;
}
let obj = g();
obj.a; // undefined

如果在this前面增加yield,使用new命令就无法生成g的实例了,g返回的是内部的一个指针。

function * g() {
    yield this.x = 2;
    yield this.y = 3;
}
new g(); // 创建不了g的实例但是该对象是一个Iterator对象,具有next方法。

如果想将Generator函数当做正常的构造函数使用,可以使用以下变通的方法。

function * g() {
    yield this.x = 2;
    yield this.y = 3;
}
var obj = {};
var f = g.bind(obj)();
obj // { x:2, y:3 }

七、应用

1、异步操作的同步化表达

Genterator函数具有暂停执行效果,可以把异步操作写在yield语句中,当该异步操作完成之后,调用Generator的next方法。

function * main() {
    var result = yield request("http://some.url"); //将异步操作写在yield语句中
    var resp = JSON.parse(result);
    console.log(resp.value);
}
// 整个main函数是用同步的方式表示的,但是yield控制了在调用第一次yield的时候只执行了第一句代码,在makeAjax中调用异步操作成功之后,通过next再调用接下来的代码。
function request(url) {
    makeAjax(url, function(response) {
        it.next(response); //异步操作完成调用接下来的语句
   });
}
var it = main();
it.next(); //调用异步操作
  • 注意在上面代码中请求成功之后再调用next一定要传入返回的值,因为yield表达式本身没有返回值。(只执行yield后面的语句,下次从结束的地方开始,不设置next值,result为undefined
  • 如果下面的操作依赖于多个异步请求,可以使用数组的形式。(控制流管理)
function * parallelDownloads() {
    let [text1, text2] = yield [
        taskA,
        taskB
   ];
   console.log(text1, text2);
}

2、部署Iterator接口

可以利用Genterator接口在任何对象上部署Iterator接口。
可以获取到Object的所有key(Object.keys),再遍历对象,将key和value添加到yield中。
然后实例化该Genterator函数传入对象即可。

3、作为数据解构

Genterator可以看做数据解构,可以为任意表达式提供类似数组的接口(yield里的值可以是任意类型)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值