ES6之Map資料結構
1.Map
含義
JavaScript 的物件(Object),本質上是鍵值對的集合(Hash 結構),但是傳統上只能用字串當作鍵。這給它的使用帶來了很大的限制。
為了解決這個問題,ES6 提供了 Map 資料結構。它類似於物件,也是鍵值對的集合,但是“鍵”的範圍不限於字串,各種型別的值(包括物件)都可以當作鍵。也就是說,Object 結構提供了“字串—值”的對應,Map 結構提供了“值—值”的對應,是一種更完善的 Hash 結構實現。如果你需要“鍵值對”的資料結構,Map 比 Object 更合適。
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
事實上,不僅僅是陣列,任何具有 Iterator 介面、且每個成員都是一個雙元素的陣列的資料結構都可以當作Map建構函式的引數。這就是說,Set和Map都可以用來生成新的 Map。
const set = new Set([
['foo', 1],
['bar', 2]
]);
const m1 = new Map(set);
m1.get('foo') // 1
const m2 = new Map([['baz', 3]]);
const m3 = new Map(m2);
m3.get('baz') // 3
2. 屬性和操作方法
- size屬性:返回Map的成員的數量,例如map.size,返回數字
- Map.protottype.set(key,value):給Map設定鍵名key和鍵值value,返回Map,如果key已有值,鍵值更新,可以鏈式使用
- Map.prototype.get(key):讀取key對應的鍵值,如果找不到就返回undefined
- Map.prototype.has(key):返回布林值,判讀某個鍵是否在Map中
- Map.prototype.detele(key):刪除指定鍵,成功返回true
- Map.prototype.clear():清除所以成員,沒有返回值
3.遍歷
- Map的遍歷方法和set基本一樣
- Map.prototype.keys():返回鍵名的遍歷器
- Map.prototype.values():返回鍵值的遍歷器
- Map.prototype.entries():返回所以成員的遍歷器
- Map.prototype.forEach():遍歷Map的所以成員
- for…of:等同於使用map.entries()
需要特別注意的是,Map 的遍歷順序就是插入順序。
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
for (let key of map.keys()) {
console.log(key);
}
// "F"
// "T"
for (let value of map.values()) {
console.log(value);
}
// "no"
// "yes"
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
// 或者
for (let [key, value] of map.entries()) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
// 等同於使用map.entries()
for (let [key, value] of map) {
console.log(key, value);
}
// "F" "no"
// "T" "yes"
4.於其他資料結構轉換
- Map轉陣列–擴充套件運算子
const myMap = new Map()
.set(true, 7)
.set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
- 陣列轉Map
new Map([
[true, 7],
[{foo: 3}, ['abc']]
])
// Map {
// true => 7,
// Object {foo: 3} => ['abc']
// }
- Map轉物件–就是遍歷之後再放入物件中
如果所有 Map 的鍵都是字串,它可以無損地轉為物件。
function strMapToObj(strMap) {
let obj = Object.create(null);
for (let [k,v] of strMap) {
obj[k] = v;
}
return obj;
}
const myMap = new Map()
.set('yes', true)
.set('no', false);
strMapToObj(myMap)
// { yes: true, no: false }
如果有非字串的鍵名,那麼這個鍵名會被轉成字串,再作為物件的鍵名。
- 物件轉Map
物件轉為 Map 可以通過Object.entries()。
let obj = {"a":1, "b":2};
let map = new Map(Object.entries(obj));
也可以遍歷物件再set
function objToStrMap(obj) {
let strMap = new Map();
for (let k of Object.keys(obj)) {
strMap.set(k, obj[k]);
}
return strMap;
}
objToStrMap({yes: true, no: false})
// Map {"yes" => true, "no" => false}
- Map轉JSON``
Map 轉為 JSON 要區分兩種情況。一種情況是,Map 的鍵名都是字串,這時可以選擇轉為物件 JSON。就是先轉物件在用stringify轉JSON
function strMapToJson(strMap) {
return JSON.stringify(strMapToObj(strMap));
}
let myMap = new Map().set('yes', true).set('no', false);
strMapToJson(myMap)
// '{"yes":true,"no":false}'
另一種情況是,Map 的鍵名有非字串,這時可以選擇轉為陣列 JSON。就是先轉陣列在用stringify轉JSON
function mapToArrayJson(map) {
return JSON.stringify([...map]);
}
let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
mapToArrayJson(myMap)
// '[[true,7],[{"foo":3},["abc"]]]'
- JSON轉Map
JSON 轉為 Map,正常情況下,所有鍵名都是字串。就是先轉物件,在遍歷物件set入Map
function jsonToStrMap(jsonStr) {
return objToStrMap(JSON.parse(jsonStr));
}
jsonToStrMap('{"yes": true, "no": false}')
// Map {'yes' => true, 'no' => false}
但是,有一種特殊情況,整個 JSON 就是一個陣列,且每個陣列成員本身,又是一個有兩個成員的陣列。這時,它可以一一對應地轉為 Map。這往往是 Map 轉為陣列 JSON 的逆操作。就是滿足格式直接new
function jsonToMap(jsonStr) {
return new Map(JSON.parse(jsonStr));
}
jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
// Map {true => 7, Object {foo: 3} => ['abc']}```
**5.注意**
- 如果對同一個鍵多次賦值,後面的值將覆蓋前面的值。
```javascript
const map = new Map();
map
.set(1, 'aaa')
.set(1, 'bbb');
map.get(1) // "bbb"
- 如果讀取一個未知的鍵,則返回undefined。
new Map().get('asfddfsasadf')// undefined
- 只有對同一個物件的引用,Map 結構才將其視為同一個鍵。這一點要非常小心。
const map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
//下面程式碼中,變數k1和k2的值是一樣的,但是它們在 Map 結構中被視為兩個鍵。
const map = new Map();
const k1 = ['a'];
const k2 = ['a'];
map
.set(k1, 111)
.set(k2, 222);
map.get(k1) // 111
map.get(k2) // 222
上面程式碼的set和get方法,表面是針對同一個鍵,但實際上這是兩個不同的陣列例項,記憶體地址是不一樣的,因此get方法無法讀取該鍵,返回undefined。
Map 的鍵實際上是跟記憶體地址繫結的,只要記憶體地址不一樣,就視為兩個鍵
如果 Map 的鍵是一個簡單型別的值(數字、字串、布林值),則只要兩個值嚴格相等,Map 將其視為一個鍵,比如0和-0就是一個鍵,布林值true和字串true則是兩個不同的鍵。另外,undefined和null也是兩個不同的鍵。雖然NaN不嚴格相等於自身,但 Map 將其視為同一個鍵。
let map = new Map();
map.set(-0, 123);
map.get(+0) // 123
map.set(true, 1);
map.set('true', 2);
map.get(true) // 1
map.set(undefined, 3);
map.set(null, 4);
map.get(undefined) // 3
map.set(NaN, 123);
map.get(NaN) // 123
個人對阮一峰大佬的《ECMAScript入門》簡單總結,詳細請戳:
https://es6.ruanyifeng.com/?search=map&x=0&y=0#docs/set-map
相關文章
- ES6之Set和Map資料結構資料結構
- ES6 Map 資料結構資料結構
- ES6的Set、Map資料結構 陣列資料結構陣列
- Redis基礎資料結構之MapRedis資料結構
- Map 資料結構資料結構
- Java資料結構之Map學習總結Java資料結構
- ES6的Set和Map資料結構,由你製造資料結構
- Java常用資料結構之Map-HashMapJava資料結構HashMap
- Set和Map資料結構。資料結構
- js資料結構--字典(map)JS資料結構
- 【Go進階—資料結構】mapGo資料結構
- ES6 Set 資料結構資料結構
- ECMAScript-新的資料結構Map資料結構
- go中map的資料結構理解Go資料結構
- 例說資料結構&STL(九)——map資料結構
- 例說資料結構&STL(十一)——hash_map/unordered_map資料結構
- 理解 Golang 的 map 資料結構設計Golang資料結構
- 資料結構小白系列之資料結構概述資料結構
- ES6 系列之模擬實現一個 Set 資料結構資料結構
- (精華)2020年7月3日 JavaScript高階篇 ES6(Map資料結構)JavaScript資料結構
- 資料結構之「樹」資料結構
- 資料結構之「棧」資料結構
- 資料結構之——棧資料結構
- 資料結構之棧資料結構
- 資料結構之圖資料結構
- 資料結構學習之樹結構資料結構
- 資料結構之「連結串列」資料結構
- 資料結構之連結串列資料結構
- Redis 資料結構 之 SDSRedis資料結構
- 資料結構之「B樹」資料結構
- 資料結構之「AVL樹」資料結構
- 資料結構之「佇列」資料結構佇列
- 資料結構之「陣列」資料結構陣列
- js資料結構之棧JS資料結構
- JavaScript資料結構之-棧JavaScript資料結構
- 資料結構之「霍夫曼樹」資料結構
- 資料結構之堆(Heap)資料結構
- 資料結構之陣列資料結構陣列