Iterator(迭代器)

迭代器(Iterator):它是一种接口,为各类不一样的数据结构提供统一的访问机制。任何数据结构,只要部署了Iterator接口,就能够完成遍历(这里主要指for...of)操做。数组

在ES6中,有三类数据结构原生具有Iterator接口:数组、相似数组的对象、以及Set和Map结构。bash

为了让一个对象可遍历,咱们须要为这个对象添加一个名为Symbol.iterator的方法(一个特殊的内置标记)。 想要让for...of去循环这个对象必须通过下列步骤:数据结构

  • 当使用for...of去遍历对象时,首先会去找该对象有没有一个名为Symbol.iterator的方法(若是没有找到将会报错)
  • for...of循环开始时,将会调用这个Symbol.iterator方法
  • 该方法必须返回一个迭代器对象(且里面含有next方法)
  • 当for...of循环开始去获取对象的值的时候,它就会调用next方法来获取
  • next()方法返回的结果是对象的形式{value: '任何值均可以', done: false}或{value:undefined, done: true}; value也就是你要获取的值,done表示你要获取的值是否已经所有获取完毕(迭代是否结束了)。若已经所有获取了,done就为true,此后再调用next方法时,done仍是true。

如下是模拟next方法返回值的例子函数

let arr = [5,10,15];
  function Iterator(arr) {
    let index = 0;
    return {
      next () {
        if(index < arr.length) {
          return {value: arr[index++],done: false};
        } else {
          return {value: undefined,done: false};
        }
      }
    }
  }
  let it = Iterator(arr);
  console.log(it.next()); //{value: 5, done: false}
  console.log(it.next()); //{value: 10, done: false}
  console.log(it.next()); //{value: 15, done: false}
  console.log(it.next()); //{value: undefined, done: false}
  console.log(it.next()); //{value: undefined, done: false}
复制代码

以上代码定义了一个Iterator函数,这个函数是遍历器生成函数(至关于Symbol.iterator方法),以后会说到Symbol.iterator方法,调用这个函数时,会返回一个迭代器对象。再调用next()方法就会返回{value:'任何值',done:Boolean}对象。next方法用来移动指针,第一次调用时,指针指向数组的第一个位置;第二次调用时,指向第二个位置......这样就能够遍历到数组的每个位置,进而获取数组的每一个元素的值ui

let arrayLike = {
    0: 'name',
    1: 'age',
    2: 'address',
    length: 3
  };
  Object.prototype[Symbol.iterator] = function () {
    let index = 0;
    let current = this;
    return {
      next () {
        if(index < current.length) {
          return {value: current[index++], done: false};
        } else {
          return {value: undefined, done: true}
        }
      }
    }
  };
  //这样当使用for...of循环时会去自动调用Symbol.iterator()方法,返回一个迭代器对象以后
  //又会去调用next方法
  for(let i of arrayLike) {
    console.log(i);  //name age address
  }
复制代码

还能够经过类部署Iterator接口。Symbol.iterator属性对于一个函数,执行后返回当前对象的迭代器对象。this

class Iterator {
    constructor (obj) {
      this.start = 0;
      this.end = obj.length
    }
    [Symbol.iterator] () {
      return this;
    }
    next () {
      if(this.start < this.end) {
        return {value: obj[this.start++], done: false};
      } else {
        return {value: undefined, done: true};
      }
    }
  }
  let obj = {
    0: 'name',
    1: 'age',
    length: 2
  };
  let it = new Iterator(obj);
  // console.log(it.next());
  // console.log(it.next());
  // console.log(it.next());
  for(let j of it) {
    console.log(j);  //name age
  }
复制代码

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

let obj = {
    0: 'a',
    1: 'b',
    2: 'c',
    length: 3,
    [Symbol.iterator]: Array.prototype[Symbol.iterator]
  };
  for(let j of obj) {
    console.log(j);  //将会打印出a,b,c
  }
复制代码

注意普通对象部署Symbol.iterator方法并没有效果 prototype

字符串也是能够迭代的 : for...of循环能够将字符串的每一个字符循环出来指针

let str = 'hello';
for(let j of str) {
    console.log(j);  // h e l l o
}
复制代码
相关文章
相关标签/搜索