Iterator遍历器
JS原有表示集合(collection)的数据结构,主要由数组、对象,ES6又增加了Map与Set,这样就有4种数据集合。
由于四种数据结构实现方式不同,这样就需要一种统一的接口机制,统一处理不同的数据结构
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何部署了该接口的类,都能完成遍历操作
要明确以下两点
- Iterator针对数组结构
- res(...)数组与对象都可以
1. 遍历方法
es6创造了for...of
循环,of
后接受一个iterator对象, iterator接口主要依靠这个进行遍历
for(let value of itrator) {
console.log(value)
}
let result = it.next()
while(!result.done) {
let value = result.value
// do somethings
result = it.next();
}
2. next方法()
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,这个属性是一个函数,执行这个函数,会返回一个iterator。
const it = [1,2,3][Symbol.iterator]()
it.next() // logs { value : 1, done : false }
真实的iterator遍历过程是这样的。
- 创建一个指针对象,指向当前数据结构的起始位置,也就是说遍历器的本质是一个指针
- 第1次调用next,指向数据结构的第1个成员
- 第2次调用next,指向数据结构的第2个成员
- 不断调用指针对象的next方法,直到它指向数据结构的结束位置
每一次调用next方法,都会返回数据结构的当前成员信息,也就是 { value , done },其中 value是当前成员的值,done是一个布尔值,表示遍历是否结束
注意 : 对象没有部署iterator接口(因为对象的访问顺序不确定),常见的部署了iterator结构数据结构有 Set Map String Array arguments NodeList
3. 手动部署iterator接口
一个对象如果要具备可被for...of循环调用的 Iterator 接口,就必须在Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。
(1). 手动为类对象部署itrator (这样依然不能适用for of循环与...,只是做一个模拟)
class A {
constructor(value,stop) {
this.value = value
this.stop = stop
}
[Symbol.iterator]() {
let current = 0
const arr = Object.keys(this).map(key=> ({key : this[key]}))
const next = ()=> {
return { value : arr[current++],done : current === arr.length ? true : false }
}
return { next }
}
}
const a = new A('我在乐园里遨游','做一条真实的懒狗')
const it = a[Symbol.iterator]()
it.next()
it.next()
对象暂时不清楚怎么部署一个iterator才能适用for of循环
(2). 对于类数组对象,可以通过以下方式部署(对象没有作用)
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. 常见的底层使用iterator的情景
- 对数组与set结构进行结构赋值,会默认调用[Symbol.iterator]
- 扩展运算符对数组、字符串
- yield* 后面跟一个可遍历的结构,它会调用该结构的遍历器接口
- for of
- Array.from()
- Promise.all()
- Promise.race()
5. 遍历器对象的 return(),throw()
iterator对象除了具有next方法,也可以具有return throw方法
return方法的使用场合是,如果for...of循环提前退出(通常是因为出错,或者有break语句),就会调用return方法。
如果一个对象在完成遍历前,需要清理或释放资源,就可以部署return方法。
以下两种情况都会触发return方法
for(let value of iterator) {
break;
}
for(let value of iterator) {
throw new Error();
}
6. for ... of 的好处
- 对比for循环,代码量少了
- 对比forEach方法,for...of可以中途退出,forEach不行
- for... in ,遍历数组键名,还会遍历手动添加的其他键,甚至包括原型链上的键(这一点绝对错误,for in不会遍历原型链上的键)
集合家族关系
让我们来理清他们之间的关系,以及集合、字典之间的关系
集合是由无序且唯一的项组成,这个数据结构使用了与有限集合相同的数学概念,并广泛应用在计算机科学的数据结构中。
你可以把集合想象成一个没有重复元素的键值对对象组成的且无序的数组。
以下是集合的实现类
名称 | 说明 |
---|---|
Set | 无序集合,集合元素表示 {key : key } |
Direction | 字典,也是集合实现的一种类,但它的元素为表示 { key : value },即键值对 |
HashTable | 又称为HashMap,他是字典类的一种散列表实现方式,它的目标是根据散列函数尽快找到对应的索引,从而快速定位目标值 |
Map | es2015增加的map类,属于es6 |
网友评论