接着上文[js高手之路] es6系列教程 - 迭代器與生成器詳解繼續. html
在es6中引入了一個新的循環結構for ....of, 主要是用來循環可迭代的對象,那麼什麼是可迭代的對象呢?es6
可迭代的對象通常都有Symbol.iterator屬性,你能夠在控制檯中用console.dir打印數組,Map,Set,在他們的原型對象(prototype)上面就能找到。這個屬性與迭代器密切相關,經過該函數能夠返回一個迭代器,下文,我會舉一個例子。通常來講全部的集合對象(數組,Set,Map 以及字符串)都是可迭代的對象。這些對象中都有默認的迭代器.json
for..of循環的遍歷原理:數組
循環每執行一次都會調用可迭代對象的next()方法, 並將迭代器返回的結果對象的value屬性存儲在一個變量中,循環將持續執行這一過程,直到done返回true函數
1 let values = [ 10, 20, 30 ]; 2 for( let val of values ) { 3 console.log( val ); 4 }
這段for...of循環的代碼經過調用values數組的Symbol.iterator方法來獲取迭代器, 這一步是由js引擎自動完成的,隨後迭代器的next()方法被屢次調用,返回對象的value值並存儲在變量val中,依次爲: 10, 20, 30,done爲true的時候退出,最後 不會把undefined賦值給val.this
利用Symbol.iterator訪問默認的迭代器spa
1 let userList = [ 'ghostwu', '悟空', '八戒' ]; 2 let iterator = userList[Symbol.iterator](); 3 console.log( iterator.next() ); //{ value : 'ghostwu', done : false } 4 console.log( iterator.next() ); //{ value : '悟空', done : false } 5 console.log( iterator.next() ); //{ value : '八戒', done : false } 6 console.log( iterator.next() ); //{ value : undefined, done : false }
因爲具備Symbol.iterator屬性的對象都有默認的迭代器,這個特性能夠用來檢測對象是否爲可迭代對象.prototype
1 function isIterable( obj ){ 2 return typeof obj[Symbol.iterator] === 'function'; 3 } 4 console.log( isIterable( [ 10, 20 ,30 ] ) ); //true 5 console.log( isIterable( "ghostwu" ) ); //true 6 console.log( isIterable( new Map() ) ); //true 7 console.log( isIterable( new Set() ) ); //true 8 console.log( isIterable( new Object() ) ); //false 9 console.log( isIterable( {} ) );//false
因此,for..of不能遍歷對象( json )code
var obj = { name : 'ghostwu', age : 22, sex : 'man' }; for( var val of obj ) { console.log( val ); }
上面這種遍歷方式,就會報錯.htm
可是,咱們能夠爲對象增長一個迭代器方法
1 let obj = { 2 items : [], 3 *[Symbol.iterator](){ 4 for( let item of this.items ) { 5 yield item; 6 } 7 } 8 } 9 obj.items.push( 10 ); 10 obj.items.push( 20 ); 11 obj.items.push( 30 ); 12 var iterator = obj[Symbol.iterator](); 13 console.log( iterator.next() ); //{ value : 10, done: false } 14 console.log( iterator.next() ); //{ value : 20, done : false } 15 console.log( iterator.next() ); //{ value : 30, done : false } 16 console.log( iterator.next() ); //{ value : undefined, done : true }
給Symbol.iterator屬性添加一個生成器,那麼對象就具有迭代器的功能了,那麼就可以使用for...of方法了
1 let obj = { 2 items : [], 3 *[Symbol.iterator](){ 4 for( let item of this.items ) { 5 yield item; 6 } 7 } 8 } 9 obj.items.push( 10 ); 10 obj.items.push( 20 ); 11 obj.items.push( 30 ); 12 13 for ( let val of obj ) { 14 console.log( val ); 15 }
內置迭代器:
可迭代的對象,都內置如下3種迭代器
entries(): 返回一個迭代器,值爲鍵值對
values(): 返回一個迭代器, 值爲集合的值
keys(): 返回一個迭代器,值爲集合中的全部鍵
1 let userList = [ 'ghostwu', '悟空', '八戒' ]; 2 3 for ( let name of userList.entries() ) { 4 console.log( name ); 5 } 6 7 let set = new Set( [ 10, 20, 30 ] ); 8 for ( let num of set.entries() ){ 9 console.log( num ); 10 } 11 12 let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] ); 13 for ( let detail of map.entries() ){ 14 console.log( detail ); 15 }
entries返回的是鍵值對,注意Set集合,返回的鍵和值是同樣的.
1 let set = new Set( [ 10, 20, 30 ] ); 2 for ( let num of set.values() ){ 3 console.log( num ); 4 } 5 6 let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] ); 7 for ( let detail of map.values() ){ 8 console.log( detail ); 9 }
1 let set = new Set( [ 10, 20, 30 ] ); 2 for ( let num of set.keys() ){ 3 console.log( num ); 4 } 5 6 let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] ); 7 for ( let detail of map.keys() ){ 8 console.log( detail ); 9 }
默認的迭代器:
1 let userList = [ 'ghostwu', '悟空', '八戒' ]; 2 3 //至關於調用values 4 for ( let name of userList ) { 5 console.log( name ); 6 } 7 8 let set = new Set( [ 10, 20, 30 ] ); 9 //至關於調用values 10 for ( let num of set ){ 11 console.log( num ); 12 } 13 14 let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] ); 15 //至關於調用entries 16 for ( let detail of map ){ 17 console.log( detail ); 18 }
Map的默認行爲,能夠用解構來簡寫:
1 let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] ); 2 for ( let [ key, value ] of map ) { 3 console.log( key + '--->' + value ); 4 }
利用展開運算符把Set與Map轉化成數組
1 let set = new Set( [ 10, 20, 30 ] ); 2 let arr = [...set]; 3 console.log( arr ); // [10,20,30] 4 5 let map = new Map( [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ]); 6 console.log( [...map] ); // [ [ 'name', 'ghostwu' ], [ 'age', 22 ] ] 7 8 let arr1 = [ 10, 20, 30 ]; 9 let arr2 = [ 'ghostwu', '八戒', '悟空' ]; 10 let combine = [ ...arr1, ...arr2, 'done' ]; 11 console.log( combine ); // [10, 20, 30, "ghostwu", "八戒", "悟空", "done"]