zoukankan      html  css  js  c++  java
  • es6之iterator,for...of

    遍历器(Iterator)是一种统一的接口机制,来处理所有不同的数据结构。

    JavaScript 原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6 又添加了MapSet。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是MapMap的成员是对象。这样就需要一种统一的接口机制,来处理所有不同的数据结构。

    Iterator 的作用有三个:

     一是为各种数据结构,提供一个统一的、简便的访问接口;

     二是使得数据结构的成员能够按某种次序排列;

    三是 ES6 创造了一种新的遍历命令for...of循环

    每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含valuedone两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。

    {
      let arr=['hello','world'];
      let map=arr[Symbol.iterator]();
      console.log(map.next());
      console.log(map.next());
      console.log(map.next());
    }
    //{value: "hello", done: false}
    // {value: "world", done: false}
    //{value: undefined, done: true}

    ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名Symbol.iterator,它是一个表达式,返回Symbol对象的iterator属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内.

    const obj = {
      [Symbol.iterator] : function () {
        return {
          next: function () {
            return {
              value: 1,
              done: true
            };
          }
        };
      }
    };

    原生具备 Iterator 接口的数据结构如下。

    • Array
    • Map
    • Set
    • String
    • TypedArray
    • 函数的 arguments 对象
    • NodeList 对象
    let arr = ['a', 'b', 'c'];
    let iter = arr[Symbol.iterator]();
    
    iter.next() // { value: 'a', done: false }
    iter.next() // { value: 'b', done: false }
    iter.next() // { value: 'c', done: false }
    iter.next() // { value: undefined, done: true }

    上面代码中,变量arr是一个数组,原生就具有遍历器接口,部署在arrSymbol.iterator属性上面。所以,调用这个属性,就得到遍历器对象。

    对于原生部署 Iterator 接口的数据结构,不用自己写遍历器生成函数,for...of循环会自动遍历它们。除此之外,其他数据结构(主要是对象)的 Iterator 接口,都需要自己在Symbol.iterator属性上面部署,这样才会被for...of循环遍历。

    {
      let obj={
        start:[1,3,2],
        end:[7,9,8],
        [Symbol.iterator](){
          let self=this;
          let index=0;
          let arr=self.start.concat(self.end);
          let len=arr.length;
          return {
            next(){
              if(index<len){
                return {
                  value:arr[index++],
                  done:false
                }
              }else{
                return {
                  value:arr[index++],
                  done:true
                }
              }
            }
          }
        }
      }
      for(let key of obj){
        console.log(key);
      }
    }
    //1
    //3
    //2
    //7
    //8
    //9

    对于类似数组的对象(存在数值键名和length属性),部署 Iterator 接口,有一个简便方法,就是Symbol.iterator方法直接引用数组的 Iterator 接口。

    let iterable = {
      0: 'a',
      1: 'b',
      2: 'c',
      length: 3,
      [Symbol.iterator]: Array.prototype[Symbol.iterator]
    };
    for (let item of iterable) {
      console.log(item); // 'a', 'b', 'c'
    }

    因为上面这个对象的键名是类似于数组下标的数字,所以可以直接引用数组的iterator.

    普通对象部署数组的Symbol.iterator方法,并无效果。

    let iterable = {
      a: 'a',
      b: 'b',
      c: 'c',
      length: 3,
      [Symbol.iterator]: Array.prototype[Symbol.iterator]
    };
    for (let item of iterable) {
      console.log(item); // undefined
    }

    有了遍历器接口,数据结构就可以用for...of循环遍历.

  • 相关阅读:
    poj 1226
    在Excel中创建和使用ServerDocument
    Linux进程管理—信号、定时器
    《linux程序设计》--读书笔记--第十四章信号量、共享内存和消息队列
    POJ 1054 The Troublesome Frog
    boost库在工作(37)网络UDP服务端之七
    指纹增强程序Hong_enhancement
    读书笔记——Windows核心编程(15)在应用程序中使用虚拟内存
    蓝牙技术谈之调频技术(一)
    android使用全局变量的两种方法
  • 原文地址:https://www.cnblogs.com/sunmarvell/p/9147573.html
Copyright © 2011-2022 走看看