ES6的Generator函数

1.简介

    Generator函数是一个函数的内部状态的遍历器(也就是说,Generator函数是一个状态机)。    形式上,Generator函数是一个普通函数,但是有两个特征。
  • function命令与函数名之间有一个星号*;
  • 函数体内部使用yield语句,定义遍历器的每个成员,即不同的内部状态。
    function* helloWorldGenerator() {
        yield ‘hello‘;
        yield ‘world‘;
        return ‘ending‘;
    }
    let hw = helloWorldGenerator();
   console.log(hw.next());// { value: ‘hello‘, done: false }
    console.log(hw.next());// { value: ‘world‘, done: false }
    console.log(hw.next());// { value: ‘ending‘, done: true }
    console.log(hw.next());// { value: undefined, done: true }

总结:

  • 调用Generator函数,返回一个部署了Iterator接口的遍历器对象,用来操作内部指针。
  • 以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。
  • value属性表示当前的内部状态的值,是yield语句后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

2.next方法的参数

yield语句本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。
    function* f() {
        for(let i=0; true; i++) {
            var reset = yield i;
            if(reset) { i = -1; }
        }
    }
    let g = f();
    console.log(g.next()); // { value: 0, done: false }
    console.log(g.next()); // { value: 1, done: false }
    console.log(g.next(true));// { value: 0, done: false }
上面代码先定义了一个可以无限运行的Generator函数f,如果next方法没有参数,每次运行到yield语句,变量reset的值总是undefined。 当next方法带一个参数true时,当前的变量reset就被重置为这个参数(即true),因此i会等于-1,下一轮循环就会从-1开始递增。

3.for...of循环

for...of循环可以自动遍历Generator函数,且此时不再需要调用next方法。
function *foo() {
    yield 1;
    yield 2;
    yield 3;
    yield 4;
    yield 5;
    return 6;
}
for (let v of foo()) {
    console.log(v);// 1 2 3 4 5
}
上面代码使用for...of循环,依次显示5个yield语句的值。注意:一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象,所以上面代码的return语句返回的6,不包括在for...of循环之中。下面是一个利用generator函数和for...of循环,实现斐波那契数列的例子。
function* fibonacci() {
    let [prev, curr] = [0, 1];
    for (;;) {
        [prev, curr] = [curr, prev + curr];
        yield curr;
    }
}
for (let n of fibonacci()) {
    if (n > 1000) break;
    console.log(n);
}
从上面代码可见,使用for...of语句时不需要使用next方法。

4.throw方法

Generator 函数内部还可以部署错误处理代码,捕获函数体外抛出的错误。
    function* gen(x){
        try {
            var y = yield x + 2;
        } catch (e){
            console.log(e);
        }
        return y;
    }
    let g = gen(1);
    g.next();
    g.throw(‘出错了‘);// 出错了
上面代码的最后一行,Generator 函数体外,使用指针对象的 throw 方法抛出的错误,可以被函数体内的 try ... catch 代码块捕获。这意味着,出错的代码与处理错误的代码,实现了时间和空间上的分离,这对于异步编程无疑是很重要的。

5.yield*语句

如果yield命令后面跟的是一个遍历器,需要在yield命令后面加上星号,表明它返回的是一个遍历器。这被称为yield*语句。其实yield关键字就是以一种更直观、便捷的方式让我们创建用于遍历有限序列集合的迭代器,而yield则用于将生成器函数的代码切片作为有限序列集合的元素(元素的类型为指令+数据,而不仅仅是数据而已)。下面我们一起看看yield关键字是怎样对代码切片的吧! 定义生成器函数
function *enumerable(msg){
    document.write(msg)
    var msg1 = yield msg + ‘  after ‘
    document.write(msg1)
    var msg2 = yield msg1 + ‘ after‘
    document.write(msg2 + ‘ over‘)
}
//上述代码最终会被解析为下面的代码:

var enumerable = function(msg){
    var state = -1
    return {
        next: function(val){
            switch(++state){
                case 0:
                    document.write(msg + ‘ after‘)
                    break
                case 1:
                    var msg1 = val
                    document.write(msg1 + ‘ after‘)
                    break
                case 2:
                    var msg2 = val
                    document.write(msg2 + ‘ over‘)
                    break
            }
        }
    }
}

6.作为对象属性的Generator函数

如果一个对象的属性是Generator函数,可以简写成下面的形式。
    let obj1 = {
    * myGeneratorMethod() {

    }
};
//上面代码中,myGeneratorMethod属性前面有一个星号,表示这个属性是一个Generator函数。
//它的完整形式如下,与上面的写法是等价的。
    let obj2 = {
        myGeneratorMethod: function* () {

        }
    };

此篇终,待续……

时间: 2024-10-07 06:32:59

ES6的Generator函数的相关文章

【es6】Generator 函数

1. 基本概念 状态机,封装了多个内部状态 2. 应用 返回一个遍历器对象. 3. 代码形式 function* helloWorldGenertor() { yield 'hello'; yield 'world'; return 'ending'; } var hw = helloWorldGenertor(); 调用 hw.next() hw.next() // { value: 'hello', done: false } hw.next() // { value: 'world', d

ES6 Generator函数

Generator函数是es6提供的解决异步编程的方案之一:Generator函数是一个状态机,内部封装了不同状态的数据: <script type="text/javascript"> // generator定义 function后面跟个*号 function* myGenerator(){ console.log('业务逻辑A') let result=yield 'hello' console.log(result) console.log('业务逻辑B') yie

es6 中的generator函数控制流程

Generator函数跟普通函数的写法有非常大的区别: 一是,function关键字与函数名之间有一个星号: 二是,函数体内部使用yield语句,定义不同的内部状态(yield在英语里的意思就是"产出"). 最简单的Generator函数如下: function* g() { yield 'a'; yield 'b'; yield 'c'; return 'ending'; } g(); // 返回一个对象 g函数呢,有四个阶段,分别是'a','b','c','ending'. Gen

ES6基础知识(Generator 函数应用)

1.Ajax 是典型的异步操作,通过 Generator 函数部署 Ajax 操作,可以用同步的方式表达 function* main() { var result = yield request("http://some.url"); var resp = JSON.parse(result); console.log(resp.value); } function request(url) { makeAjaxCall(url, function(response){ it.nex

js-ES6学习笔记-Generator函数的异步应用

1.ES6 诞生以前,异步编程的方法,大概有下面四种. 回调函数 事件监听 发布/订阅 Promise 对象 Generator 函数将 JavaScript 异步编程带入了一个全新的阶段. 2.所谓"异步",简单说就是一个任务不是连续完成的,可以理解成该任务被人为分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段. 3.JavaScript 语言对异步编程的实现,就是回调函数.所谓回调函数,就是把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候

js-ES6学习笔记-Generator函数的应用

1.异步操作的同步化表达 Generator函数的暂停执行的效果,意味着可以把异步操作写在yield语句里面,等到调用next方法时再往后执行.这实际上等同于不需要写回调函数了,因为异步操作的后续操作可以放在yield语句下面,反正要等到调用next方法时再执行.所以,Generator函数的一个重要实际意义就是用来处理异步操作,改写回调函数. function* loadUI() { showLoadingScreen(); yield loadUIDataAsynchronously();

generator函数学习笔记

一.基本概念 Generator函数是一种可以暂停执行,返回iterator对象的函数,yield是暂停标识 function* gen(){ yield 1; yield 2; } Generator函数在function后面有一个*,内部有yield语句 function* gen(){ yield 1; yield 2; return '1' } let g = gen(); //调用Generator函数返回遍历器对象 console.log(g.next())//{"value&quo

es6之Generator

1.Generator函数其实是一个封装了多个内部状态的状态机,执行它会返回一个遍历器对象,然后可以依次遍历Generator中的每一个状态,也就是分段执行,yield是暂停执行的标记,next恢复执行. 2.yield: - 一个函数里面,return只能执行一遍,yield可以执行多次: - Generator函数可以不用yield,这时就是一个简单的暂缓执行函数: - yield只能用在Generator函数里: - yield如果用在一个表达式里,必须放在圆括号里 function* f

js-ES6学习笔记-Generator函数

1.Generator 函数是 ES6 提供的一种异步编程解决方案.形式上,Generator 函数是一个普通函数,但是有两个特征.一是,function关键字与函数名之间有一个星号:二是,函数体内部使用yield语句,定义不同的内部状态. 2.Generator函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号.不同的是,调用Generator函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是上一章介绍的遍历器对象(Iterator Object