美文网首页
iterators & generators-《unde

iterators & generators-《unde

作者: aliyu | 来源:发表于2017-05-31 18:55 被阅读20次

    前言

    果然不能立flag,上次文章都写完了,可是hexo出了点小问题,再加上正好回家,所以延后了几天。

    发现之前一直提到 迭代器 和 生成器的字眼。其实一直没有讲这方面的东东。iterators 在es6中应用的还是挺广的,set,map,array,string都有这样的入口,generators是es7中async的基础。个人认为还是挺重要的。

    iterators

    很多语言都有iterators的概念。
    在ES6中:
    for-of循环基于iterators
    ...(扩散操作符)基于iterators
    甚至异步程序也用到iterators

    为什么需要iterators

    循环存在的问题

    需要多个变量去标记它,通用的比如i,len;
    (其实这点我个人还不是很能理解)

    iterators是什么

    iterators是一个拥有next()方法的对象,每次调用next()方法,返回一个下面的结构

    {
      done: false, //表示是否到达循环的终点
      value: //该项的值
    }
    

    ES6中内建的iterators

    集合对象

    ES6 有三个类型的集合对象

    • Arrays
    • Maps
    • Sets

    他们都有以下的方法

    • entries(),返回一个[key,value]的iterators
      • Arrays返回的key为数字序号
      • Sets,返回的key和value一样的值
      • Maps,返回的key为正常的key
    • keys(),返回key的iterators
      • 跟entries()中返回key是一样的
    • values(),返回一个values的iterators
      • 跟entries()中返回value是一样的

    如果不指定迭代器方法的话,
    Arrays和Sets调用的是values(),Maps调用的是entries()

    判断一个对象是不是迭代器 typeoof Object[Symbol.iterator] === 'function'

    String迭代器

    ES5中string存在效率低,无法识别双字节字符的情况。
    ES6中解决了无法识别双字节字符的bug

    NodeList迭代器

    在ES5 中DOM的Nodelist和arrays区别很容易让人困惑
    ES6为DOM的Nodelist也增加了一个默认的迭代器,同数组一样,所以也可以使用for-of去循环

    ...操作符

    ...操作符是从迭代器中读取数据并依次插入的

    generators

    什么是generators

    • generators是一个返回值是iterators的函数
    • generators在function关键字后有号并且内部有yield关键字,号不一定要紧跟在function关键字后面
    • 生成器执行时会在每次yield后停止执行,注:yield关键字只能存在于generators内部
    • 书写在对象内部的方法
    let o1 = {
      createIterator:function*(){
    
      }
    }
    
    let o2 = {
      *createIterator(){
    
      }
    }
    //这两种都可以
    

    generator 传参

    往next()内传参的话,会替换掉上次yield的返回值。

    function *createIterator(){
      let first = yield 1;
      let second = yield first + 2;
      yield second + 3;
    }
    let iterator = createIterator();
    
    iterator.next() //{value:1,done:false}
    iterator.next(4) //{value:6,done:false}
    iterator.next(5)//{value:8,done:true}
    

    generator 抛异常

    iterator.throw()

    • 在预计抛出异常的时候,可以用try..catch捕获
    • 如果异常被捕获,则throw()相当于next()返回的结果
    • 如果generator内有return ,则return 后面的代码均不会执行

    generator内可嵌套generator

    异步任务执行

    利用generator的特性执行多个异步任务,后续可以用Promise()进行改造

    普通任务

    该任务不需要利用上一步任务的返回值。

    function run (tasks){
      let task = tasks();
      let result = task.next();
    
      function step (){
        if(!result.done){
          result = task.next();
          step();
        }
      }
    
      step();
    }
    
    
    run(function * (){
      console.log(1);
      yield;
      console.log(2);
      yield;
      console.log(3);
    })
    

    带数据的任务

    其实只变动了一处,将数据放在next()函数内部

    function run (tasks){
      let task = tasks();
      let result = task.next();
    
      function step (){
        if(!result.done){
          result = task.next(result.value);
          step();
        }
      }
    
      step();
    }
    

    异步运行任务

    如果result.value是一个函数

    //假想的函数
    function readFile(filename){
      return function(cb){
        fs.readFile(filename,cb);
      };
    }
    
    function run (tasks){
      let task = tasks();
      let result = task.next();
    
      function step(){
        if(!result.done){
          if(typeof result.value === 'function'){
            result.value(function(err,data){
              if(err){
                task.throw(err);
              }else{
                task.next(data);
                step();
              }
            })
          }
    
        }
      }
    
      step();
    }
    

    从上文代码中可以看的出来缺点:

    • 必须要求函数为err优先
    • 两个函数的参数传递依赖于next()

    相关文章

      网友评论

          本文标题:iterators & generators-《unde

          本文链接:https://www.haomeiwen.com/subject/hjgdfxtx.html