美文网首页
Iterator(迭代器)

Iterator(迭代器)

作者: 抽疯的稻草绳 | 来源:发表于2020-12-23 09:26 被阅读0次

    概念

    JavaScript原有的表示集合的数据结构有数组(Array)和对象(Object),ES6又添加了Map和Set。这样就有了4种数据集合,此时便需要一种统一的接口机制来处理不同的数据结构。

    Iterator对象

    1.Iterator就是这样一个统一的接口。任何数据结构,主要部署Iterator接口,就可以完成遍历。
    2.Iterator接口主要供for...of使用(ES6创造的新的遍历命令)
    3.Iterator对象本质上是一个指针对象。(创建时指向数据结构头部,依次调用next()方法后指针会移动,依次指向第1,2,3...个成员,最后指向结束位置)

    next()方法
    next()方法每次调用输出数据结构的成员。是一个包含value和done两个属性的对象。
    形如:{value:当前成员的值,done:true/false} done代表是否循环结束

    let color = ['red','yellow','blue']
    let iterator = createIterator(colors);//createIterator如下自定义
    iterator.next();//{value:'red',done:false}
    iterator.next();//{value:'yellow',done:false}
    iterator.next();//{value:'blue',done:false}
    iterator.next();//{value:undefined,done:true}
    //模拟实现createIterator:返回一个遍历器对象。
    function createIterator(arr){
       var index = 0;
       return {
           next(){
           return index < arr.length ? { value:arr[index++],done:false} : { value:undefined,done:true}
          }
      }
    }
    

    默认迭代器

    当使用for...of循环时,该循环会自动寻找Iterator接口。
    ES6规定,一个数据结构只要具有Symbol.iterator属性,就是可遍历的。

    const obj = {//obj具有Symbol.iterator(它是一个方法),因此是可遍历的
      [Symbol.iterator]:function(){
           return {
               next:function(){
                   return {
                       value:1,
                       done:true
                  }
              }
          }
      }
    }
    

    ES6的有些数据结构(数组)原生部署了Symbol.iterator属性(称为部署了遍历器接口),即不用任何处理就可以被for...of循环。另外一些数据结构(对象)没有。
    以下数据结构原生部署Iterator接口:也就是说这些都可以使用for...of。除了这些,其他数据结构(如对象)的Iterator接口需要自己在Symbol.iterator属性上面部署,才会被for...of遍历。

    • Array
    • Map
    • Set
    • String
    • TypedArray
    • 函数的arguments对象
    • NodeList对象
    //数组的默认迭代器:
    let color = ['red','yellow','blue']
    let arrIt = color[Symbol.iterator]();//返回一个迭代器
    arrIt.next()//{value:'red',done:false}
    //类数组arguments的默认迭代器:
    function fn(){
       let argsIt = arguments[Symbol.iterator]();
       argsIt.next()
    }
    //类数组dom节点的默认迭代器:
    let myP = document.getElementsByTagName('li');
    let pIt = myP[Symbol.iterator]();
    pIt.next();
    //字符串的默认迭代器:
    let str = 'dhakjda';
    let strIt = str[Symbol.iterator]();
    strIt.next();
    //对象没有默认(即内置)迭代器:obj[Symbol.iterator] is not a function
    

    Iterator使用场景
    1.for of

    //迭代器使用场景
    //1.for of 循环:底层调用的是iterator.自动调用next().大部分使用迭代器都是使用它
    //好处:1.语义化好 2.可以break
    //for...of与其他遍历语法比较:
    //1)for循环缺陷:1.不易理解 2.i,j变量不好管理容易混乱
    //2)forEach缺陷:不能跳出循环,break/return均无效
    //3)for in.1.不易理解 2.会循环出不是当前索引的值:另外添加的属性(自身的或者原型上的) xx.name=yy 总之:为对象设计的,不适合遍历数组
    //4)for of优点:1.和for in一样简洁 2.可以跳出循环 3.提供统一操作接口
    
    let colors = ['red','yellow','blue']
    for(let color of colors){//数组
    if(color == 'yellow')break;
       console.log(color);
    }
    function fn(){
       //let argsIt = arguments[Symbol.iterator]();
       //argsIt.next()
       for(let item of arguments){//arguments
           console.log(item)
      }
    }
    for(let item of myP){//dom节点
       console.log(item)
    }
    

    2.数组新增方法
    //keys:返回index

    //keys:返回index
    let colors = ['red','yellow','blue']
    for(let item of colors.keys()){//colors.keys()返回一个迭代器
       console.log(item)//0,1,2
    }
    //entries:返回包含value,index的数组
    for(let [index,color] of colors.entries()){//colors.entries()返回一个迭代器
       console.log(index,color)//0 'red' 1 'yellow' 2 'blue'
    }
    

    3.数组的解构赋值

    //对数组和Set结构解构赋值时,本质上也是调用Symbol.iterator()。
    [index,color] = [0,'red']
    

    4....扩展运算符

    //扩展运算符也会调用默认的Iterator接口:转化为数组
    let colors = ['red','yellow','blue']
    let colors2 = ['black',...colors];//本质上也是使用迭代器
    

    相关文章

      网友评论

          本文标题:Iterator(迭代器)

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