Iterator

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

Iterator的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。

在ES6中,有些数据结构原生具备Iterator接口(比如数组),即不用任何处理,就可以被for...of循环遍历,有些就不行(比如对象)。原因在于,这些数据结构原生部署了Symbol.iterator属性(详见下文),另外一些数据结构没有。凡是部署了Symbol.iterator属性的数据结构,就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。

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

一个为对象添加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 };
        }
      }
    };
  }
};

有一些场合会默认调用Iterator接口:

  • 解构赋值

  • 扩展运算符(...)

  • yield* 后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。

  • 由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用

字符串是一个类似数组的对象,也原生具有Iterator接口。

遍历器对象除了具有next方法,还可以具有return方法和throw方法。如果你自己写遍历器对象生成函数,那么next方法是必须部署的,return方法和throw方法是否部署是可选的.

for...of 、forEach 和 for...in 的区别

forEach

对数组的每一个元素执行一次提供的函数(不能使用return、break等中断循环),不改变原数组,无返回值undefined。

let arr = ['a', 'b', 'c', 'd']
arr.forEach(function (val, idx, arr) {
    console.log(val + ', index = ' + idx) // val是当前元素,index当前元素索引,arr数组
    console.log(arr)
})

输出:

a, index = 0
(4) ["a", "b", "c", "d"]
b, index = 1
(4) ["a", "b", "c", "d"]
c, index = 2
(4) ["a", "b", "c", "d"]
d, index = 3
(4) ["a", "b", "c", "d"]

for…of

它是ES6中新增加的语法,用来循环获取一对键值对中的值。

一个数据结构只有部署了 Symbol.iterator 属性, 才具有 iterator接口可以使用 for of循环

所以可以用来循环遍历数组,而不能循环遍历对象

let arr = ['China', 'America', 'Korea']
for (let o of arr) {
    console.log(o) //China, America, Korea
}

// error
let obj = {a: '1', b: '2', c: '3', d: '4'}
for (let o of obj) {
    console.log(o)   //Uncaught TypeError: obj[Symbol.iterator] is not a function
}

for…in

循环遍历的值都是数据结构的键值

let obj = {a: '1', b: '2', c: '3', d: '4'}
for (let o in obj) {
    console.log(o)    //遍历的实际上是对象的属性名称 a,b,c,d
    console.log(obj[o])  //这个才是属性对应的值1,2,3,4
}
 posted on 2021-06-04 21:41  kly99  阅读(66)  评论(0)    收藏  举报