往期回顾:
前端开发必备 - ES6 新特性之 let 和 const 命令
前端开发必备 - ES6 新特性之 变量的解构赋值
前端开发必备 - ES6 新特性之 字符串的拓展
前端开发必备 - ES6 新特性之 正则的拓展
前端开发必备 - ES6 新特性之 数值的拓展
前端开发必备 - ES6 新特性之 对象的拓展
前端开发必备 - ES6 新特性之 Symbol
前端开发必备 - ES6 新特性之 Set和Map数据结构
前端开发必备 - ES6 新特性之 Proxy
前端开发必备 - ES6 新特性之 Promise对象
13.1 Iterator遍历器概念
Iterator是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
Iterator三个作用:
- 为各种数据结构,提供一个统一的、简便的访问接口;
- 使得数据结构的成员能够按某种次序排列;
- Iterator 接口主要供ES6新增的for...of消费;
13.2 Iterator遍历过程
- 创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
- 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
- 第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
- 不断调用指针对象的next方法,直到它指向数据结构的结束位置。
每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含value和done两个属性的对象。
- value属性是当前成员的值;
- done属性是一个布尔值,表示遍历是否结束;
模拟next方法返回值:
13.3 默认Iterator接口
若数据可遍历,即一种数据部署了Iterator接口。
ES6中默认的Iterator接口部署在数据结构的Symbol.iterator属性,即如果一个数据结构具有Symbol.iterator属性,就可以认为是可遍历。
Symbol.iterator属性本身是函数,是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名Symbol.iterator,它是一个表达式,返回Symbol对象的iterator属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内(参见《Symbol》一章)。
原生具有Iterator接口的数据结构有:
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
13.4 Iterator使用场景
- (1)解构赋值 对数组和 Set 结构进行解构赋值时,会默认调用Symbol.iterator方法。
- (2)扩展运算符 扩展运算符(...)也会调用默认的 Iterator 接口。
- (3)yield* yield*后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。
- (4)其他场合 由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用了遍历器接口。下面是一些例子。
- for...of
- Array.from()
- Map(), Set(), WeakMap(), WeakSet()(比如new Map([['a',1],['b',2]]))
- Promise.all()
- Promise.race()
13.5 for...of循环
只要数据结构部署了Symbol.iterator属性,即具有 iterator 接口,可以用for...of循环遍历它的成员。也就是说,for...of循环内部调用的是数据结构的Symbol.iterato方法。
使用场景:
for...of可以使用在数组,Set和Map结构,类数组对象,Genetator对象和字符串。
- 数组 for...of循环可以代替数组实例的forEach方法。
与for...in对比,for...in只能获取对象键名,不能直接获取键值,而for...of允许直接获取键值。
- Set和Map 可以使用数组作为变量,如for (let [k,v] of b){...}。
- 类数组对象
- 对象
- 普通对象不能直接使用for...of会报错,要部署Iterator才能使用。
13.6 跳出for...of
使用break来实现。
公众号:前端自习课