zoukankan      html  css  js  c++  java
  • ES6 的遍历器接口 Iterator

    一、概念

    遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

    Iterator的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6有一种新的遍历方式,for...of,而Iterator的主要作用,就是支持此操作。

    二、是否具备遍历器(Iterator)接口

    在ES6中,有些数据结构原生具备Iterator接口(比如数组),即不用任何处理,就可以被for...of循环遍历,有些就不行(比如对象)。原因在于,这些数据结构原生部署了Symbol.iterator属性(详见下文),另外一些数据结构没有。

    凡是部署了Symbol.iterator属性的数据结构,就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。

    在ES6中,有三类数据结构原生具备Iterator接口:数组、某些类似数组的对象、Set和Map结构。它们三者不需要我们手动部署Symbol.iterator属性就可以使用for...of遍历功能。而普通对象使用for...of遍历就会报错,因为它没有部署该接口。

    三、部署接口

    如果你需要使原本不具备for...of遍历功能的集合具备该功能,就需要手动为它部署。ES6有许多内置的Symbol值,这些就是接口。

    下面我们利用迭代器中的原理来给对象生成一个迭代器,实现让对象可以使用for...of

    var person={
              name: 'zz',
               age: 18
           }
    //给person对象添加一个iterator接口 person[Symbol.iterator] = function(){
    //使用object.keys()方法把j对象中的k值读取出来存在数组当中 var arr = Object.keys(person); var i = 0; return { //ES6中next()迭代方法,自动迭代 next(){ if(i < arr.length){ //如果done为false,继续迭代 return { //返回迭代的最后结果,如果是一个对象,那么for of的时候需要用解构 value: { k : arr[i], val: person[arr[i++]] }, done: false } }else{ //如果done为true,继续迭代 return { value: null, done : true } } } } }
    //解构获取返回得到的对象,输出k值,val值 for(var {key,val} of person){ console.log(key,val); }

    我们可以看到:

    1、通过为person对象部署Symbol.iterator接口,就使它实现了for...of 功能。

    2、Symbol.iterator中返回一个对象,该对象包含一个next() 方法,定义了遍历功能。

    3、next方法中的value和done,value是遍历过程中返回的键值对信息,done是一个表示遍历是否结束的布尔值。

    补充:

    1、遍历器对象除了具有next方法,还可以具有return方法和throw方法。如果你自己写遍历器对象生成函数,那么next方法是必须部署的,return方法和throw方法是否部署是可选的。

      当一个解构在遍历的时候异常提前退出(比如break,continue或者出错)的时候,就会调用return方法,其次,return方法必须返回一个对象。

      至于throw方法,则是用于抛出错误,Generator.prototype.throw这里不展开讲了,感兴趣的可以搜索一下。

    2、用ES6新功能Generator函数来实现Symbol.iterator接口,事半功倍。

    var yieldIterator = {};
    yieldIterator[Symbol.iterator] = function* () {
        yield 1;
        yield 2;
        yield 3;
    };
    
    [...yieldIterator] // [1, 2, 3]

    注意,yield* 后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。

    对Generator不了解的可以戳 ES6 Generator的语法 ,这里不多说。

    3、至于可以使用Array.from转换成数组的类数组对象,部署iterator有一种很简单的方法,即直接使用数组的[Symbol.iterator]接口。

    fakeArray.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

    四、默认调用Iterator接口的场景

    1、解构赋值

    2、扩展运算符(...)

    3、上文提到的 yield*

    4、由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,都默认调用,如

      for...of

      Array.from()

      Map(), Set(), WeakMap(), WeakSet()

      Promise.all()

      Promise.race()

    5、字符串是一个类似数组的对象,原生也具有Iterator接口

  • 相关阅读:
    04 类与对象
    03 方法
    02-JAVA语法基础
    大道至简第二章 读后感
    leetcode 65 有效数字
    leetcode 670 最大交换
    leetcode 49 字母异位词分组
    leetcode 71 简化路径
    leetcode 2 两数相加
    java compareTo 与 equals 区别
  • 原文地址:https://www.cnblogs.com/Double-Zhang/p/8920671.html
Copyright © 2011-2022 走看看