概念
Iterator - 遍历器 是一种接口,为各种不同的数据结构提供统一的访问机制。也就是说只要拥有了 Iterator 接口就可以完成统一访问遍历操作。
作用
- 为不同的数据结构提供统一的访问机制;
- 使得数据结构的成员能够按照某种次序排序;
- 为 ES6 for…of 调用。
应用
凡是部署了 Iterator 属性的数据结构,称为部署了遍历器接口。调用这个接口,会返回一个遍历器对象。
ES6 中 数组、伪数组、Set 和 Map 结构,原生具备 Iterator 接口。主要有一下应用场景:
- for…of;
- 数组解构赋值;
- 扩展运算符(…);
- yield * 是一个可遍历的结构;
- 数组遍历;
- 字符串遍历;
- 参数遍历;
实现
添加 Symbol.iterator 来为当前对象添加遍历器接口。
遍历器对象必须有 next 方法,还可以可选 return 方法和 throw 方法。
let obj = {
data: ['one', 'two'],
}
; (function () {
for (let i of obj) { // TypeError: obj is not iterable
console.log('initial i', i)
}
})()
obj[Symbol.iterator] = function () {
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
}
}
}
}
}
obj[Symbol.iterator] = Array.prototype[Symbol.iterator];
; (function () {
for (let i of obj) {
console.log('deal i', i) // deal i one deal i two
}
})()
for…of 使用原理
for (let item of ['one', 'two']) {
console.log('item', item);
statements...
}
var $iterator = Array.prototype[Symbol.iterator]();
var $result = $iterator.next();
while (!$result.done) {
item = $result.value;
statements...
$result = $iterator.next();
}
对于 伪数组 可以直接调用数组的 Array.prototype[Symbol.iterator] 而对于普通对象部署 Array.prototype[Symbol.iterator] 方法,并无效果
const arr = {
0: 'one',
1: 'two',
length: 2
}
(function () {
arr[Symbol.iterator] = Array.prototype[Symbol.iterator];
for (const i of arr) {
console.log('arr i', i) //arr i one arr i two
}
})()