遍历器(
Iterator
)本质是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator
接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
作用:
- 为各种数据结构,提供一个统一的、简便的访问接口;
- 使得数据结构的成员能够按某种次序排列;
- ES6 创造了一种新的遍历命令
for...of
循环,Iterator
接口主要供for...of
消费。
执行方式
-
调用
Iterator
接口,返回一个指针对象,指向当前数据结构的起始位置,但是它不会立即执行,也就是说第一步仅仅是返回一个只针对象; -
第一次调用指针对象的
next
方法,可以将指针指向数据结构的第一个成员。 -
第二次调用指针对象的
next
方法,指针就指向数据结构的第二个成员。 -
不断调用指针对象的
next
方法,直到它指向数据结构的结束位置。
模拟 Iterator
接口运行。
function myIterator(array) {
// 通过 闭包 保存当前指针的位置
let nextIndex = 0;
return {
next: function() {
return nextIndex < array.length
? { value: array[nextIndex++], done: false }
: { value: undefined, done: true };
}
};
}
const it = myIterator(['a', 'b', 'c']);
it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: "c", done: false }
it.next() // { value: undefined, done: true }
默认的 Iterator
接口
ES6 规定,默认的 Iterator 接口部署在数据结构的
Symbol.iterator
属性,或者说,一个数据结构只要具有Symbol.iterator
属性,就可以认为是“可遍历的”。
原生具备 Iterator
接口的数据结构如下。
- Array
- Map
- Set
- String
- 函数的 arguments 对象
- NodeList 对象
也给对象添加 Iterator
接口。
const obj = {
a: 123,
b: 321,
c: 456,
[Symbol.iterator]: function() {
let i = 0;
return {
next: function () {
let obj = {}
if (i === 0) {
obj = {
value: 123,
done: false
}
} else if (i === 1) {
obj = {
value: 321,
done: false
}
} else if (i === 2) {
obj = {
value: 456,
done: false
}
} else {
obj = {
value: undefined,
done: true
}
}
i++;
return obj;
}
};
}
}
for (let val of obj) {
console.log(val) // 123, 321, 456
}
与扩展预算符
只要实现了
Iterator
结构,扩展运算符(…)就可以调用默认的 Iterator 接口,转为数组。
// 例一
var str = 'hello';
[...str] // ['h','e','l','l','o']
// 例二
let arr = ['b', 'c'];
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd']
// 例三
var obj = {
a: 123,
[Symbol.iterator]: function () {
let i = 0
return {
next: function () {
i++;
if (i === 1) {
return {
value: i,
done: false
}
} else {
return {
value: undefined,
done: true
}
}
}
}
}
}
var arr = [2, ...obj]
console.log(arr); // [2, 1]