一、Iterator(迭代器)的概念
含义:Iterator (迭代器)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历该数据结构所有成员的操作。
原生具备 Iterator 接口的数据结构如下:
- Array
- Map
- Set
- String
- 函数的 Arguments 对象
- DOM 的 Nodelist 对象
- TypedArray
ES6规定:默认的 Iterator 接口部署在 Symbol.iterator 属性,Symbol.iterator 是内置的 Symbol 值,内置的 Symbol 值可以作为【对象】的属性,扩展对象的行为。Symbol.iterator 是一个表达式,必须放在中括号内;它本质是个函数,是当前数据结构默认的迭代器生成函数,执行该函数会返回一个迭代器。
示例:默认的 Iterator 接口
//声明一个数组
const arr = ['hello', 'world', 'nihao']
//执行数组的 Symbol.iterator方法,得到数组默认的 Iterator 接口
const iterator = arr[Symbol.iterator]()
一种数据结构只要部署了 Iterator 接口,就称该数据结构是可遍历的(iterable)。
二、Iterator 的迭代过程
**
- 调用迭代器生成函数,返回一个指针对象(迭代器的本质),指向数据结构的起始位置
- 第一次调用迭代器的 next() 方法,指针指向数据结构的第一个成员(next() 方法是 Iterator 的默认方法),next() 方法的返回值是一个对象,包含当前数据结构成员的信息,有value和done两个属性,value对应该成员的值,done对应布尔值,如果遍历还在进行,值为false,如果遍历结束,值为true
- 不断调用 next() 方法,直到指针指向数据结构的结束位置
**
示例:数组的 Iterator 接口调用next方法(接上一个例子)
const arr = ['hello', 'world', 'nihao']
const iterator = arr[Symbol.iterator]()
console.log(iterator.next())//{value: "hello", done: false}
console.log(iterator.next())//{value: "world", done: false}
console.log(iterator.next())//{value: "nihao", done: false}
console.log(iterator.next())//{value: undefined, done: true}
注意:遍历完所有成员后,继续调用next方法时,value的值为undefined
对象(Object)没有默认部署 Iterator 接口,就必须在 Symbol.iterator属性上部署迭代器生成方法。
示例:给 banji 部署 Iterator 接口,遍历 stus 数组中的成员
//声明一个对象
const banji = {
name: "终极一班",
stus: [
'xiaoning',
'xiaoming',
'xiaotian',
'knight'
],
//部署迭代器生成方法
[Symbol.iterator](){
//保存外层this
const _this = this
//索引变量
let index = 0
return {
next(){
if(index < _this.stus.length){
return {value: _this.stus[index++], done: false}
}else{
return {value: undefined, done: true}
}
}
}
}
}
//测试
const iterator = banji[Symbol.iterator]()
console.log(iterator.next())//{value: "xiaoning", done: false}
console.log(iterator.next())//{value: "xiaoming", done: false}
console.log(iterator.next())//{value: "xiaotian", done: false}
console.log(iterator.next())//{value: "knight", done: false}
console.log(iterator.next())//{value: undefined, done: true}
三、for…of 循环
实际上,Iterator 接口主要供 for…of 循环消费,也就是指,使用 for…of 循环,会自动调用当前数据结构的 Symbol.iterator 属性方法。
示例:直接使用 for…of 遍历 banji(接上一个例子)
for (let v of banji){
console.log(v)
}
/*
xiaoning
xiaoming
xiaotian
knight
*/
其它默认调用 Iterator 的常见场合如下:
- 解构赋值:对于数组和 Set 结构的解构赋值
- 扩展运算符
- yield *:后跟一个可遍历的数据结构时,会调用该结构的 Iterator 接口
- 任何接收数组作为参数的场合,如:Array.from()
四、总结
Iterator 的主要作用具备如下:
- 为各种数据结构提供统一、简便的访问接口
- 使得数据结构的成员能够按照某种次序排列
- ES6新的遍历命令 for…of 循环,Iterator 主要供 for…of 消费
转载出处:
ECMAScript 6 入门
作者:阮一峰
https://es6.ruanyifeng.com/#docs/iterator