1. 程式人生 > >[js高手之路] es6系列教程 - 叠代器,生成器,for...of,entries,values,keys等詳解

[js高手之路] es6系列教程 - 叠代器,生成器,for...of,entries,values,keys等詳解

== 我會 item 獲取 prot ron 原型對象 檢測 ges

接著上文[js高手之路] es6系列教程 - 叠代器與生成器詳解繼續.

在es6中引入了一個新的循環結構for ....of, 主要是用來循環可叠代的對象,那麽什麽是可叠代的對象呢?

可叠代的對象一般都有Symbol.iterator屬性,你可以在控制臺中用console.dir打印數組,Map,Set,在他們的原型對象(prototype)上面就能找到。這個屬性與叠代器密切相關,通過該函數可以返回一個叠代器,下文,我會舉一個例子。一般來說所有的集合對象(數組,Set,Map 以及字符串)都是可叠代的對象。這些對象中都有默認的叠代器.

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.

利用Symbol.iterator訪問默認的叠代器

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屬性的對象都有默認的叠代器,這個特性可以用來檢測對象是否為可叠代對象.

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 )

var obj = {
    name : ‘ghostwu‘,
    age : 22,
    sex : ‘man‘
};
for( var val of obj ) {
    console.log( val );
}

上面這種遍歷方式,就會報錯.

但是,我們可以為對象增加一個叠代器方法

 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"]

[js高手之路] es6系列教程 - 叠代器,生成器,for...of,entries,values,keys等詳解