一、概述
1、一種接口,為各種不同的數據結構提供統一的訪問機制。任何數據結構只要部署Iterator接口,就可以完成遍歷操作
2、調用指針對象的next
方法,就可以遍歷事先給定的數據結構
3、每一次調用next
方法,都會返回數據結構的當前成員的信息。具體來說,就是返回一個包含value
和done
兩個屬性的對象。其中,value
屬性是當前成員的值,done
屬性是一個布爾值,表示遍歷是否結束。
4、凡是部署了Symbol.iterator
屬性的數據結構,就稱為部署了遍歷器接口。調用這個接口,就會返回一個遍歷器對象。
二、數據結構的默認Iterator接口
1、對象的Symbol.iterator
屬性,指向該對象的默認遍歷器方法。
2、具備Iterator接口的原生數據結構:
- 數組
- 某些類似數組的對象
- Set和Map結構。
3、其他數據結構(主要是對象)的Iterator接口,都需要自己在Symbol.iterator
屬性上面部署,這樣才會被for...of
循環遍歷
4、嚴格地說,對象部署遍歷器接口並不是很必要,因為這時對象實際上被當作Map結構使用
5、對一般對象部署迭代器對象:
/** * * @authors Soul (2461358597@qq.com) * @date 2016-06-01 15:34:02 * @version 0.0.1 * @description 給一般對象部署迭代器對象 */ //迭代器對象 const soul_iterator={ soul_index:-1, [Symbol.iterator](){ return this; }, next(){ var arr=this.soul_exchange(); this.soul_index++; return this.soul_index>=arr.length?{value:undefined,done:true}:{value:this[arr[this.soul_index]],done:false}; }, soul_exchange(){ var array=[];//用來存放數字索引和屬性名的鍵值對 var j=0;//用作array數組的索引值 for(let i in this){ if(i!="soul_index"&&i!="next"&&i!="soul_exchange") array[j++]=i; } // console.log(array); return array; } }; //測試對象 function objTest(){} objTest.prototype={ name:"soul", age:21 }; //部署迭代器對象 objTest.prototype.__proto__=soul_iterator; //創建測試對象的實例 var newObj=new objTest(); // for...of 測試 for(let i of newObj){ console.log(i); } //next()方法測試 // console.log(newObj.next()); // console.log(newObj.next()); // console.log(newObj.next()); // console.log(newObj.next());
6、對於類似數組的對象(存在數值鍵名和length屬性),部署Iterator接口,有一個簡便方法,就是Symbol.iterator
方法直接引用數組的Iterator接口
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
7、如果Symbol.iterator
方法對應的不是遍歷器生成函數(即會返回一個遍歷器對象),解釋引擎將會報錯
三、調用Iterator接口的場合
1、默認調用Iterator接口的情況:
- 解構賦值
- 擴展運算符 //只要某個數據結構部署了Iterator接口,就可以對它使用擴展運算符,將其轉為數組
- yield* //yield*后面跟的是一個可遍歷的結構,它會調用該結構的遍歷器接口
- for...of
- Array.from()
- Map(), Set(), WeakMap(), WeakSet()(比如
new Map([['a',1],['b',2]])
) - Promise.all()
- Promise.race()
四、字符串的Iterator接口
1、字符串是一個類似數組的對象,也原生具有Iterator接口。
五、Iterator接口和Generator函數
1、Generator可以很容易的實現Iterator接口
2、實現方式:
var myIterable = {}; myIterable[Symbol.iterator] = function* () { yield 1; yield 2; yield 3; };
3、yield命令給出每一步的返回值。
六、Iterator對象的return()和throw()
1、next方法是必須部署的,return
方法和throw
方法是否部署是可選的
2、return方法必須返回一個對象
3、return方法主要用於提前退出
4、throw方法主要是配合Generator函數使用,一般的遍歷器對象用不到這個方法
七、for...of
1、凡是部署了Iterator對象的對象,都可以使用for...of取得值