生成器和迭代器

一、Generator生成器函数

Generator函数是ES2015提出的异步的解决方案,与普通的函数有很大的不同;

生成器提供了一种【中断机制】,使得子程序可以暂时返回,等在之后的某个时刻,继续回来运行。

特点:

(1)generator函数与普通函数不同,普通函数一旦调用就会执行完,但是generator函数中间可以暂停,执行一会歇一会。

(2)在function关键字后面跟一个(*)号;

(3)在函数体内部使用yield表达式作为一个状态,实现暂停;

(4)generator函数执行并不会有什么效果,而是返回一个迭代器对象,之后调用迭代器的next方法会返回一个值对象。

举例说明:

 

function *go(a){
     console.log(1);
     //yield语句只是标识符,并没有返回值
     //yield左边等于next()传来的参数值,没传参则为undefined,yield右边是next()的返回值
     let b=yield a;
     console.log(2);
     let c=yield b;
     console.log(3);
     return c;
 }
 let iterator=go('aaa');
 let r1=iterator.next();//第一次next()不用传参
 console.log(r1);// 1 {value: "aaa", done: false}
 
let r2=iterator.next('bbb');
 console.log(r2);//2 {value: "bbb", done: false}
 
let r3=iterator.next();
 console.log(r3);//3 {value: undefined, done: true}  done属性值代表当前迭代是否完成。

//例2
function *gen(x){
    var y=2*(yield (x+1));
    var z=yield (y/3);
    return x+y+z;
}
var t=gen(5);
console.log(t.next());//{value: 6, done: false}
console.log(t.next(12));//{value: 8, done: false}
console.log(t.next(13));//{value: 42, done: true}
//解析:yield (x+1)表达式将传递值6到外部,在第二次调用next(12)的时候,传递12到generator函数内部作为yield(x+1)表达式的值,因此y被赋值12*12=24.接下来,下一条yield(y/3)
将向外传值值8.第三次调用next(13)传递13到generator函数内部给yield(y/3),所以z的值为13

 

 

在生成器中的return值:便利返回对象的done值为true时迭代即结束,不会对该value处理。

复制代码
function *createIterator() {
  yield 1;
  return 42;
  yield 2;
}
let iterator1 = createIterator();
console.log(...iterator);   // 1
复制代码

 

async是Generator函数的语法糖。async的实现原理就是将Generator函数和自动执行器包装在一个函数里。

 相比于generator,Async函数有以下几点改进:

(1)内置执行器。generator函数的执行必须依赖执行器,而async函数自带执行器,调用的方式和普通函数的调用一样。

(2)返回值是promise对象。比起generator函数返回的iterator对象更加方便,可以直接使用then()方法调用。

 

二、Iterator迭代器

迭代器是一种特殊的对象,它具有一些专门为迭代过程设计的接口,所有的迭代器对象都有一个next()方法,每次调用都返回一个结果对象。该结果对象有两个属性:value(表示下一个将要返回的值)和done(布尔值,表示迭代过程是否结束)

 

手动实现一个简单的迭代器

测试数据:

 

 

三、可迭代对象

1、可迭代对象具有Symbol.iterator属性,是一种与迭代器密切相关的对象。

  在ES6中所有集合对象(Array、Set结构和Map结构)和String都是可迭代对象,这些对象都有默认的迭代器。

  ES6中新加入的特性for of循环需要用到可迭代对象这些功能。

  for-of循环每执行一次都会调用可迭代对象的next()方法,并将迭代器返回的结果对象的value属性存储在一个变量中,循环将持续执行这一过程直到返回对象的done属性值为true。

  通过生成器创建的迭代器也是可迭代对象,因为生成器默认会为Symbol.iterator属性赋值。

 

2、判断一个数据是否具有可迭代能力,只有当数据具有Symbol.iterator属性的时候才可以使用for-of进行迭代。

        

 

3、默认迭代器

ES6为很多内置对象提供了默认的迭代器,只有当内建的迭代器不能满足需求时才自己创建迭代器。

S6的三个集合对象:Set、Map、Array都有默认的迭代器,常用的如values()方法、entries()方法、keys()方法都返回一个迭代器。其值区别如下:

  • entries():多个键值对
  • values():集合的值
  • keys():集合的键
var obj={
    a:1,
    b:2,
    c:3
}
for(let item of obj){
    console.log(item)//Uncaught TypeError: obj is not iterable
}
for(let item of Object.keys(obj)){
    console.log(item)//a,b,c
}
for(let item of Object.values(obj)){
    console.log(item)//1,2,3
}

 

我们可以通过Symbol.iterator属性来访问可迭代对象的默认迭代器。例如对一个数组:

 

 

思考:

1、既然数组等具有可迭代能力,但是为什么我们直接用arr.next()或报错?

是因为可迭代对象不代表是一个迭代器,只有迭代器才具有next()方法。所以具有可迭代能力的对象,如果想要使用next()方法,必须先转换为迭代器。

可迭代对象不一定是迭代器,但是迭代器一定是可迭代对象。

 

 

 

co模块?

用于generator函数的自动执行。是我们可以不用编写generator函数的执行器。

co模块其实是将两种自动执行器(thunk函数和promise对象)包装成一个模块,然后返回的是promise对象。

转载于:https://www.cnblogs.com/xiaoan0705/p/11404861.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值