ES6学习:Map结构的目的和基本用法
Map結構的目的和基本用法
JavaScript的對象(Object)本質上是鍵值對的集合(Hash結構),但是只能用字符串作為鍵。這給它的使用帶來了很大的限制。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="myDiv"></div> <script type="text/javascript"> var data = {}; var element = document.getElementById("myDiv"); data[element]=element; data["[Object HTMLDivElement]"]; console.log(data); </script> </body> </html> |
上面的代碼原意是將一個DOM節點作為對象data的鍵,但是由于對象只接受字符串作為鍵名,所以element被自動轉化為字符串[Object HTMLdivElement]。
為解決這個問題,ES6提供了Map數據結構。它類似于對象,也是鍵值對的集合,但是“鍵”的范圍不限于字符串,各種類型的值(包括對象)都可以當作鍵。也就是說,Object結構提供了“字符串-值”的對應,Map結構提供了“值-值”的對應,是一種更完善的Hash結構實現。如果你需要“鍵值對”的數據結構,Map比Object更適合。
| 1 2 3 4 5 6 7 | var m = new Map(); var o = {p:"Hello World"}; m.set(o,"content"); m.get(o);//"content" m.has(o);//true m.delete(o);//true m.has(o);//false |
上面的代碼使用set方法將對象o當作m的一個鍵,然后又實用get方法讀取這個鍵,最后使用delet方法刪除了這個鍵。
作為構造函數,Map也可以接受一個數組作為參數。該數組的成員是一個個表示鍵值對的數組。
| 1 2 3 4 5 6 | var??map = new Map([["name","張三"],["title","Author"]]); console.log(map.size);//2 console.log(map.has("name"));//true console.log(map.get("name"));//張三 console.log(map.has("title"));//true console.log(map.get("title"));//"Author" |
上面的代碼在新建Map實例時就制定了兩個鍵-name和title。
Map構造函數接受數組作為參數,實際上執行的是下面的算法。
| 1 2 3 4 5 6 7 8 9 | var items= [ ["name","張三"], ["title","Author"] ]; var??map = new Map(); items.forEach(function(key,value){ map.set(key,value); }); console.log(items); |
如果對同一個鍵多次賦值,后面的值將覆蓋前面的值。
| 1 2 3 | let map = new Map(); map.set(1,'aaa').set(1,'bbb'); map.get(1);//"bbb" |
上面的代碼對鍵1連續賦值兩次,后一次的值覆蓋了前一次的值。
如果讀取一個未知的鍵,則返回undefined。
| 1 | console.log(new Map().get('adsdfdsf')); |
注意,只有對同一個對象的應用,Map結構才將其視為同一個鍵。這一點要非常小心。
| 1 2 3 | var??map =new Map(); map.set(['a'],555); console.log(map.get(['a']));//undefined |
上面的set和get 方法,表面上是針對同一個鍵,但實際上是兩個值,內存地址是不一樣的,因此get方法無法讀取該鍵,返回undefined。
同理,同樣的值的兩個實例,在Map結構中被視為兩個鍵。
| 1 2 3 4 5 6 | var map = new Map(); var k1=['a']; var k2=['a']; map.set(k1,111).set(k2,222); console.log(map.get(k1));//111 console.log(map.get(k2));//222 |
上面的代碼中,變量k1和k2的值是一樣的,但他們在Map結構中被視為兩個鍵。
由上可知,Map的鍵實際上是跟內存地址綁定的,只要內存地址不一樣,就視為兩個鍵。這就解決了同名屬性碰撞(clash)的問題,我們擴展別人的庫時,如果使用對象作為鍵名,不用擔心自己的屬性與原作者的屬性同名。
如果Map的鍵是一個簡單的值(數字、字符串、布爾值),則只要兩個值嚴格相等,Map就將其視為一個鍵,包括0和-0.另外,雖然NaN不嚴格對于自身,但Map將其視為同一個鍵。
| 1 2 3 4 5 | var map =new Map(); map.set(NaN,123); map.get(NaN);//123 map.set(-0,123); map.get(+0);//123 |
?
實例的屬性和操作方法
Map結構的實例有以下屬性和操作方法。
size屬性:size屬性返回Map結構的成員總數。
| 1 2 3 4 | var map =new Map(); map.set('foo',true); map.set('bar',false); console.log(map.size); |
set(key,value)方法
set方法設置key所對應的鍵值,然后返回整個Map結構。如果可以已經有值,則鍵值會被更新,否則就新生成該鍵。
| 1 2 3 4 | var m = new Map(); m.set("edition",6);//鍵值是字符串 m.set(262,"standard");//鍵是數值 m.set(undefined,"nah");//鍵是undefined |
set 方法返回的是Map本身,因此可以采用鏈式寫法。
| 1 | let map = new Map().set(1,'a').set(2,'b').set(3,'c'); |
get( key ):get方法讀取key對應的鍵值,如果找不到key,則返回undefined。
has( key ):has方法返回一個布爾值,表示某個鍵是否在Map數據結構中。
delete( key ):delete 方法刪除某個鍵,返回true。如果刪除失敗,返回false。
clear( ):clear方法清除所有成員,沒有返回值。
遍歷方法:
Map原生提供3個遍歷器生成函數和1個遍歷方法。
- keys( ):返回鍵名的遍歷器。
- values( ):返回鍵值的遍歷器。
- entries( ):返回所有成員的遍歷器。
- forEach( ):遍歷Map的所有成員。
下面是使用實例。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | let map = new Map([['F','no'],['T','yes']]); for (let key of map.keys()){ console.log(key); } for(let value of map.values()){ console.log(value); } for(let item of map.entries()){ console.log(item[0],item[1]); } for(let[key,value] of map.entries()){ console.log(key,value); } for(let [key,value] of map){ console.log(key,value); } |
以上最后的那個例子,表示Map結構的默認遍歷器接口(Symbol.iterator屬性)就是entries方法。
Map結構轉為數組結構比較快速的方法是結合使用擴展運算符(…)。
| 1 2 3 4 5 | let map = new Map([[1,'one'],[2,'two'],[3,'three']]); console.log([...map.keys()]); console.log([...map.values()]); console.log([...map.entries()]); console.log([...map]); |
結合數組的map方法,filter方法,可以實現Map的遍歷和過濾(Map本身沒有map 和filter方法)。
| 1 2 3 4 5 | let map0 = new Map().set(1,'a').set(2,'b').set(3,'c'); let map1 = new Map([...map0].filter(([k,v])=>k<3)); let map2 = new Map([...map0].map(([k,v])=>[k*2,'_'+v])); console.log(map1); console.log(map2); |
此外,Map還有一個forEach方法,與數組的forEach方法類似,也可以實現遍歷。
| 1 2 3 | map0.forEach(function(value,key,map0){ console.log("Key: %s, Value: %s",key,value); }); |
與其他數據結構的互相轉換
Map轉換為數組
前面已經提過,Map轉為數組最方便的方法就是使用擴展運算符(…)。
| 1 2 | let myMap =new Map().set(true,7).set({foo:3},['abc']); console.log([...myMap]); |
數組轉為Map
將數組傳入Map構造函數就可以轉為Map。
| 1 | new Map([[true,7],[{foo:3},['abc']]]); |
Map轉為對象
如果Map的所有鍵都是字符串,則其可以轉為對象。
| 1 2 3 4 5 6 7 8 9 | function strMapToObj(strMap){ let obj =Object.create(null); for(let[k,v] of strMap){ obj[k] =v; } return obj; } let myMap =new Map().set('yes',true).set('no',false); console.log(strMapToObj(myMap)); |
對象轉為Map
| 1 2 3 4 5 6 7 8 9 | function objToStrMap(obj){ let strMap =new Map(); for(let k of Object.keys(obj)){ strMap.set(k,obj[k]); } return strMap; } console.log(objToStrMap({yes:true,no:false})); |
轉載于:https://www.cnblogs.com/snowhite/p/9091803.html
總結
以上是生活随笔為你收集整理的ES6学习:Map结构的目的和基本用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PCB多层板的一些资料
- 下一篇: 所谓数据结构,对python来说不过如此