写点什么

ES6 新特性——generator

作者:猫猫巧克力
  • 2022 年 8 月 06 日
  • 本文字数:1333 字

    阅读完需:约 4 分钟

ES6新特性——generator

generator 是 ES6 的新特性。

先来复习回顾一下函数的使用方法,函数是先声明再传值调用,如下:

function foo(x){

  return x+x

}

var f1 = foo(2)  // f1==4

return 语句是设定函数的返回值,一般可以声明一个变量去接收这个返回值(此处可以联想到闭包的应用)

如果没有再函数最后写 return 语句,默认就是 return undefined

下面引出 generator 的概念:

generator 和函数很想,只不过形式上有一些差异:

function* foo(x){

    yield x + 1;

    yield x + 2;

    yield x + 3;

}

generator 与函数不同的地方是,generator 由 function*定义(注意多出来的“*”号),并且,除了 return 语句,还可以用 yield 返回多次。

那么 generator 就是一个可以返回多次的“函数”吗?

我们来看下面的例子:

以著名的斐波那契数列为例

0 1 1 2 3 5 8 13 21 34 . . .

要用函数实现斐波那契数列,可以这样写:

function fib(max){

    var t,

          a = 0,

          b = 1,

          arr = [0,1];

        while (arr.length < max){

           [a,b] = [b,a + b]

            arr.push(b)

    }

   return arr;

}

这段代码是用 while 循环方法,每次都检测一个值然后去循环遍历

如果我们用 generator 改写就可以更优化:

function* fib(max){

    var t,

          a = 0,

          b = 1,

          n = 0;

while(n<max){

          yield a;

          [a,b] = [b,a+b];

          n++;

    }

return;

}

这个时候调用 fib(5),并不会像函数一样返回我们想要的结果,而是创建了一个对象。如果要让 generator 执行,需要再写一句 var f = fib(5),然后 f.next(),这样不停的写 next()方法直到返回 done:true,表示执行完成,程序暂停。

next()方法会执行 generator 的代码,每次遇到 yield x 就返回一个对象{value:x,done:true/false}。如果 done 为 true,则 value 就是 return 的返回值。

当执行到 done 为 true 就不再继续执行了。

第二个方法是直接用 for...of 循环迭代 generator 对象,这种方式不需要我们自己判断 done:

function* fib(max){

    var t,

          a = 0,

          b = 1,

          n = 0;

while(n<max){

          yield a;

          [a,b] = [b,a+b];

          n++;

    }

return;

}

for(var x of fib(10)){  //这里也可以用 in,都一样

    console.log(x)

}

那么 generator 和普通函数相比,有什么好处?

因为 generator 可以在执行过程中多次返回,所以它看上去就像一个可以记住状态的函数,利用这一点,写一个 generator 就可以实现需要用面向对象才能实现的功能。例如,用一个对象来保存状态,我们需要这样写:

var fib = {

a:0,

b:1,

b:0,

max:5,

next:function(){

    var r = this.a,

          t = this.a + this.b;

this.a = this.b;

this.b = t;

if(this.n < this.max){

        this.n ++;

        return r;

        }else{

            return undefined;

        }

    }

};

generator 调用 ajax 可以这么写:

try {

r1 = yield ajax('http://url-1', data1);

r2 = yield ajax('http://url-2', data2);

r3 = yield ajax('http://url-3', data3);

success(r3);

}

catch (err) {

handle(err);

}

用户头像

还未添加个人签名 2022.08.04 加入

还未添加个人简介

评论

发布
暂无评论
ES6新特性——generator_8月月更_猫猫巧克力_InfoQ写作社区