• iterator接口部署


           
        es6中,能表示“集合”概念的数据类型大致有四种。  
      Array,Object,Map,Set
     
      既然是集合,那遍历便是一种基本需求。而Iterator就是为了提供一种统一的接口机制。任何的数据结构,只要部署了Iterator接口,便可以使用类似的方式完成遍历操作。
     
      当然,Iterator还有2个作用,它使数据结构的成员按某种次序排列,其次,es6有一种新的遍历方式,前面也说过,for...of,而Iterator的主要作用,就是支持此操作。
     
      Iteartor的遍历过程和C++语言一样
      1)创建一个指向数据结构起始位置的指针。(起始位置不是第一个成员的位置,起始位置使一个单独的标志位。)
      2)当调用next()方法,指针就向后移动一个位置,并返回当前位置上的成员,直到指针指向数据结构的结束位置为止。
     
      第二步中,js语言返回的的成员信息是两个,value和done,value不用介绍,done是一个表示遍历是否结束的布尔值。
     
     
    2.部署接口
      上面我们说到的部署接口,那js怎么部署接口呢。其实我们之前已经说到过,在Symbol一节中,介绍了很多es6内置的Symbol值,这些就是接口。
      es6中有三类结构生来就具有Iterator接口:数组、类数组对象、Map和Set结构。
      

    var arr = [1,2,3,4];
    let iterator = arr[Symbol.iterator]();

    console.log(iterator.next()); //{ value: 1, done: false }
    console.log(iterator.next()); //{ value: 2, done: false }
    console.log(iterator.next()); //{ value: 3, done: false }
    console.log(iterator.next()); //{ value: 4, done: false }
    console.log(iterator.next()); //{ value: undefined, done: true }

     
     
      至于对象没有布置iterator接口的原因,不知道最近大家有没有看根据《你一生的故事》拍成的电影“降临",片中出现的外星语言是一门非线性的语言。而我们说的数组,Map等结构中的成员都是有顺序的,即都是线性的结构,而对象,各成员并没有一个确定的顺序,所以遍历时先遍历谁后遍历谁并不确定。所以,给一个对象部署iterator接口,其实就是对该对象做一种线性转换。如果你有这种需要,就需要手动给你的对象部署iterator接口咯~
      如:
      
    let obj = {
        data: [ 'hello', 'world' ],
        [Symbol.iterator]() {
            const self = this;
            let index = 0;
            return {
                next() {
                    if (index < self.data.length) {
                        return {
                            value: self.data[index++],
                            done: false
                        };
                    } else {
                        return { value: undefined, done: true };
                    }
                }
            };
        }
    };
     
      可以看到,Symbol.iterator会返回一个对象,这就是一个遍历器对象,而作为遍历器对象,其必须具备的特征就是必须具备next()方法。
    我们还可以据此实现指针结构的数据结构。具体略~
     
      至于可以使用Array.from转换成数组的类数组对象,部署iterator有一种很简单的方法,即直接使用数组的[Symbol.iterator]接口。
      
    fakeArray.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
      当然,不知道你们看到next是否想到了es6的一个新玩意儿,即Generator函数。用Generator函数来实现Symbol.iterator接口,事半功倍。
        

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

    [...yieldIterator] // [1, 2, 3]

     
      注意,yield* 后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。
      其次,其它调用到遍历器的操作还有解构赋值、扩展操作符、其它任何接受数组作为参数的场合,如:
    • for...of
    • Array.from()
    • Map(), Set(), WeakMap(), WeakSet()(比如)
    • Promise.all()
    • Promise.race()
     
     
      一旦当你给你的结构部署了iterator接口,那么恭喜你,你可以使用for...of来遍历你的结构了!
     
      遍历器对象除了必须布置next方法以外,还有2个可选方法。return()和throw()。当一个解构在遍历的时候异常提前退出(比如break,continue或者出错)的时候,就会调用return方法,其次,return方法必须返回一个对象。
    至于throw方法,则是用于抛出错误,Generator.prototype.throw这里不展开讲了,感兴趣的可以搜索一下。
     
      for of循环有很多优点,比如不像for...in一样只遍历键名(甚至包括原型链上的键),而且不像foreach不能跳出循环。并且for...of为各种数据结构提供了一个统一的遍历方法。所以,尽量使用它吧~
  • 相关阅读:
    Redis string
    java 是 传值还是传址 Pass-by-value or Pass-by-reference
    IDEA 适用技巧
    测试 MD
    pyqt5 学习总结
    win10 安装anaconda 无法使用pip 报错缺少SSL模块
    Hadoop datanode无法启动
    Ansible 安装jdk
    java 安装后 不能 java javac 说找不到命令 -bash: javac: command not found
    如何去掉MapReduce输出的默认分隔符
  • 原文地址:https://www.cnblogs.com/ccnNL/p/7642809.html
Copyright © 2020-2023  润新知