1. 背景
ES6 借鉴 C++、Java、C# 和 Python 语言,引入了for…of循环,作为遍历所有数据结构的统一的方法。
一个数据结构只要部署了Symbol.iterator属性,就被视为具有 iterator 接口,就可以用for…of循环遍历它的成员。也就是说,for…of循环内部调用的是数据结构的Symbol.iterator方法。
即,Iterator就是一个遍历接口。
2. 目前已实现iterator的数据类型
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
以Array为例:
const arr = ['a', 'b', 'c', 'd']
for (const value of arr) {
console.log(value) // a b c d
}
复制代码
3. Iterator实现原理
引用官方的表达:
判断结束就是返回的数据对象中的done为true。 // {done: true, value: undefined}
4. Object类型如何创建Iterator遍历接口
4.1 方案一:Generator封装
从文章第三章可以发现,其实底层就是Generator函数, 我们用Generator包一下
jsconst obj = { a: 1, b: 2, c: 3 }
function* entries(obj) {
for (let key of Object.keys(obj)) {
yield [key, obj[key]];
}
}
for (let [key, value] of entries(obj)) {
console.log(key, '->', value);
}
// a -> 1
// b -> 2
// c -> 3
复制代码
4.2 方案二:借用数组的Iterator
Array对象是具备可迭代的,但前提是key值为数组的下标,这类对象是比较极端的,不是通用做法,仅用来开拓思路。
let iterable = {
0: 'a',
1: 'b',
2: 'c',
length: 3,
[Symbol.iterator]: Array.prototype[Symbol.iterator]
};
for (let item of iterable) {
console.log(item); // 'a', 'b', 'c'
}
复制代码
4.3 方案三:自定义Iterator方案
既然我们制定for…of是通过一次次调用next方法来获取每一次轮训的值
let obj = {
a:1,
b:2,
[Symbol.iterator](){
let index = 0;
return {
next: () => {
let keys = Object.keys(this);
return index >= keys.length ? {done: true} : {value: this[keys[index++]]}
}
}
}
};
for (let val of obj) {
console.log(val);// 1, 2
}
复制代码
5. 遍历api小结
以数组对象为例
5.1 for循环
1.使用功能最全,是最原始的遍历写法。
2.写起来比较不舒服,比较麻烦。所以数组对象提供了forEach和map方法
5.2 forEach/map
1.数组全变量遍历,api轻巧。
2.循环无法中途退出,return和break命令皆不奏效
5.3 for…in
1.api轻巧、方便。
2.for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。for…in本意是为遍历对象设计。
5.4 for…of
1.api轻巧、方便。
2.可以配合continue、break、return使用,灵活度较高
3. 前提是该遍历类型已经实现Iterator接口
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END