Iterator是一种机制,一种接口,为各类不一样的数据结构提供统一的访问机制。任何数据结构,只要部署Iterator接口,就能够完成遍历操做。遍历实际上是一种线性处理,有序的。数组
Iterator遍历的过程:bash
//获取遍历器
var arr = [1,2][Symbol.iterator]();
arr.next(); //{value: 1, done: false}
arr.next(); //{value: 2, done: false}
arr.next(); //{value: undefined, done: true}
arr.next(); //{value: undefined, done: true}
复制代码
返回的成员信息是一个对象,包含{value: any, done: boolean}。调用指针对象的next方法就能够遍历事先给定的数据结构。数据结构
因为Iterator只是把接口规范加到数据结构上,因此遍历器和所遍历的数据结构是分开的。函数
默认的Iterator接口部署在数据结构的Symbol.iterator属性上,属性对应的值就是遍历器生成函数,因此只要具备Symbol.iterator属性就能够遍历。若是Symbol.iterator方法反应的不是遍历器对象生成函数,就好报错。ui
执行Symbol.iterator属性就会返回一个遍历器对象。该对象的根本特征就是具备next方法,每次调用next就会返回一个表明当前成员的信息对象,具备value和done两个属性。spa
const obj = {
a: 'aa',
[Symbol.iterator]: function(){
return {
next(){
return {
value: 1,
done: true,
}
}
}
}
}
var objIterator = obj[Symbol.iterator]();
objIterator.next(); //{value: 1, done: true}
objIterator.next(); //{value: 1, done: true}
复制代码
当使用for...of循环遍历某种数据结构时,就会自动去寻找Iterator接口设计
//无限循环,谨慎执行
for(let value of obj){
console.log(value); //1
}
复制代码
原生具有Iterator接口的数据结构:指针
对象(Object)没有Iterator接口,由于对象属性遍历前后顺序是不肯定的。code
Symbol.iterator最简单的实现方式对象
var myIterator = {};
myIterator[Symbol.iterator] = function*(){
yield 1;
yield* [2, 3];
yield 4;
}
[...myIterator] //[1,2,3,4]
复制代码
一个数据结构只要部署了Symbol.iterator数据,就被视为具备Iterator接口,就可使用for...of循环它的成员。
for...of循环调用接口,数组的遍历接口只返回具备数字索引的属性。
var arr = [1,2];
a[3] = 3;
arr.a = 'aa';
for(let value of arr){
console.log(value);
}
// 1 2 empty 3
for(let value in arr){
console.log(value);
}
// '0' '1' '3' 'aa'
复制代码
for...in循环遍历缺点:
for...in循环主要为遍历对象而设计的,不适用于遍历数组
for...of循环遍历优势:
for...of会把数组中空值也给遍历处理
对象的遍历,最好采用Object.keys + for...of
var obj = {
a: 'aa',
b: 'bb'
};
for(let key of Object.keys(obj)){
console.log(key, obj[key])
}
//'a' 'aa'
//'b' 'bb'
复制代码