跳至主要內容

21. Iterator

Harry Xiong大约 2 分钟Web 前端JavaScriptPromise 对象JS 异步async 与 await

Iterator

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

21.1 作用

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

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

  • 供for...of语句使用

Iterator本质上是一个指针对象

###21.2 指针实现过程

  1. 创建一个指针对象,指向当前数据结构的起始位置

  2. 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员

  3. 第二次调用指针对象的next方法,指针就指向数据结构的第二个成员

  4. 不断调用指针对象的next方法,直到它指向数据结构的结束位置

一些数据结构原生就具有Iterator接口,如果没有就必须设置Iterator接口才能使用

  • 普通函数实现Iterator

    function myIter(obj){
      var i = 0;
      return {
        next(){
          var done = (i>=obj.length);
          var value = !done ? obj[i++] : undefined;
          return {
            value,
            done,
          }
        }
      }
    }
    
  • 具有Iterator接口的原生数据结构

    • Array
    • Map
    • Set
    • String
    • 函数的 arguments 对象
    • NodeList 对象
//数组的Symbol.iterator方法
var arr = ['a', 'b', 'c'];
var iter = arr[Symbol.iterator]();
//通过next()方法实现每一次的迭代器的遍历
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
/*
    value是每次遍历到的值,done代表是否将该数组遍历完全
*/
  • 类数组调用数组的Symbol.iterator方法

    var iterable = {
      0: 'a',
      1: 'b',
      2: 'c',
      length: 3,
      [Symbol.iterator]: Array.prototype[Symbol.iterator]
    };
    //for...of语句实际上就是对数组使用next()方法直到将数组遍历完全
    for (let item of iterable) {
      console.log(item); // 'a', 'b', 'c'
    }
    

    注意:

    • 普通对象部署数组的Symbol.iterator方法没有任何效果,必须是要属性值为数值,迭代器内部实际上是通过属性名的自增来实现迭代的

      var iterable = {
        a: 'a',
        b: 'b',
        c: 'c',
        length: 3,
        [Symbol.iterator]: Array.prototype[Symbol.iterator]
      };
      for (let item of iterable) {
        console.log(item); // undefined, undefined, undefined
      }
      
    • 字符串虽然是一个类数组的对象,也具有Iterator原生接口

      var someString = "hi";
      typeof someString[Symbol.iterator]
      // "function"
      
      var iterator = someString[Symbol.iterator]();
      
      iterator.next()  // { value: "h", done: false }
      iterator.next()  // { value: "i", done: false }
      iterator.next()  // { value: undefined, done: true }