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'
複製代碼