Map
Object本質上是鍵值對的集合(Hash結構),但Object只能將字串當做鍵,這就給Object帶來了很大的限制,
let data = https://www.cnblogs.com/wang-fan-w/p/{}
let s = {
name :'東方不敗'
}
data[s] = '西方求敗'
// 如果鍵傳入非字串的值,會自動為字串
console.log(data); // {[object Object]: '西方求敗'}
console.log(data['[object Object]']); // 西方求敗
為了解決這個問題,es6提供了Map資料結構,它類似于物件,也是鍵值對集合,但鍵不局限于字串,各種型別的值都可以當做鍵,
- Object結構:
字串鍵:值 - Map結構:
值鍵:值
let data2 = new Map()
let s2 = {
name : "藝術概論"
}
data2.set(s2,'中國工藝美術史')
console.log(data2.get(s2)); // 中國工藝美術史
console.log(data2); // key: {name: '藝術概論'} , value : "中國工藝美術史"

上面案例使用Map的set方法,將s2當做data2的鍵,使用get方法取值,
Map的一些常用方法
| 方法 | 說明 |
|---|---|
| set() | 為Map物件添加一個指定鍵(key)和值(value)的新元素 |
| get() | 用來獲取Map物件中指定的元素 |
| has() | 回傳boolean值,用來表明Map中是否存在該元素 |
| delete() | 洗掉對應元素 |
| size | 回傳Map的成員數 |
| clear() | 清除Map所有成員,沒有回傳值 |
let data2 = new Map()
let s2 = {
name : "藝術概論"
}
data2.set(s2,'中國工藝美術史')
data2.size; // 1
data2.has(s2); // treu
data2.delete(s2); // true
data2.has(s2); // false
data2.clear(); // undefined
Map引數
Map可以接收陣列作為引數,陣列的成員是單個單個的鍵值對的陣列
let map = new Map([
['name','東方不敗'],
['title','西方求敗']
])
console.log(map.size); // 2
console.log(map); // {"name" => "東方不敗"}, {"title" => "西方求敗"}
console.log(map.has('name')); // true
console.log(map.get('name')); // 東方不敗

注意:如果有多個相同的鍵,后面的鍵值會覆寫前面的鍵值
不僅是陣列,任何具有Iterator介面、且每個成員都是一個雙元素的陣列的資料結構,都可以當做Map建構式的引數,Set和Map也可以用來生成新的Map
Set作為引數
let set = new Set([['a',1],['b',2]])
let m = new Map(set)
console.log(m); // {'a' => 1, 'b' => 2}
console.log(m.get('a')); // 1

Map作為引數
let map2 = new Map([['text','世界現代設計史'],['name','王受之']])
let m2 = new Map(map2)
console.log(m2); // {'text' => '世界現代設計史', 'name' => '王受之'}
console.log(m2.get('text')); // 世界現代設計史
console.log(m2.get('hello')); // 讀取不存在的鍵會回傳undefined

Map只有對同一個物件的參考才視為同一個鍵
let map3 = new Map()
map3.set(['a',100])
console.log(map3.get(['a'])); // undefined
因為陣列不是參考型別,生成多個陣列,它們的記憶體地址是不一樣的,其實就是基礎資料型別和參考資料型別的應用,這里的兩個['a']看似是一樣的,其實它們根本就是兩個不同的值,Map只有對同一個物件的參考才視為同一個鍵,沒有讀取到所以回傳undefined,請看下面的例子
let map4 = new Map()
let b = ['b']
let b2 = ['b']
map4.set(b)
console.log(map4.get(b2)); // undefined
Map的值其實是跟記憶體地址系結的,記憶體地址不同,那么鍵就不同(即使名字一模一樣),在這里Map就解決了同名屬性沖突的問題,當我們使用別人的庫時,使用物件名當做鍵,就不同擔心自己的屬性與別人的屬性相同了,
如果Map的鍵是一個簡單資料型別的值,如:number、string、boolean,只要這兩個值嚴格相等,Map就視為同一個鍵,例如:0和-0就是同一個鍵,而布林值true和字串true就是不同的鍵,此外null和undefined也是不同的鍵,NaN視為同一個鍵,
let n = new Map()
n.set(0,100)
console.log(n.get(-0)); // 100
n.set(5,123)
console.log(n.get('5')); // undefined
n.set(true,100)
console.log(n.get(1)); // undefined
n.set(NaN,123)
console.log(n.get(NaN)); // 123
n.set(null,100)
console.log(n.get(null)); // 100
console.log(n.get(undefined)); // undefined
Map遍歷方法
Map提供三個遍歷器生成函式和一個遍歷方法
| 方法 | 說明 |
|---|---|
| Map.prototype.keys() | 回傳鍵名的遍歷器, |
| Map.prototype.values() | 回傳鍵值的遍歷器, |
| Map.prototype.entries() | 回傳所有成員的遍歷器, |
| Map.prototype.forEach() | 遍歷 Map 的所有成員, |
定義資料
let m3 = new Map([
['a',100],
['b',200],
['c',300]
])
keys
/* keys */
for(let k of m3.keys()){
console.log(k); // a b c
}
values
/* values */
for(let k of m3.values()){
console.log(k); // 100 200 300
}
entries
for(let k of m3.entries()){
console.log(k); // ['a', 100] ['b', 200] ['c', 300]
console.log(k[0],k[1]); // a 100 b 200 c 300
}
// 或
for(let [k,v] of m3.entries()){
console.log(k,v); // a 100 b 200 c 300
}
forEach
m3.forEach(el => console.log(el)) // 100 200 300
m3.forEach((val,index) => console.log(val,index)) // 100 'a' 200 'b' 300 'c'
Map資料結構轉換
Map轉陣列
使用擴展運算子將Map結構轉換為陣列
let a = new Map([
['a',1],
['b',2],
['c',3]
])
console.log([...a.keys()]); // ['a','b','c']
console.log([...a.values()]); // [1,2,3]
console.log([...a.entries()]); // ['a', 1] ['b', 2] ['c', 3]
console.log([...a]); // ['a', 1] ['b', 2] ['c', 3]
轉換后的陣列是一個真正的陣列,可以使用陣列方法

let back = [...a].filter((val,index) => val[1] == 2 )
console.log(back); // ['b',2]
陣列轉Map
let a2 = new Map([
['name','東方不敗'],
[{num : 3},['abc']]
])
console.log(a2); // 0: {"name" => "東方不敗"} 1: {Object => Array(1)}

Map轉物件
let a3 = new Map()
.set('a',100)
.set('b',200)
/* 通過函式傳入map */
function mapToObj(mapVal){
// 在內部創建一個空物件
let obj = {}
// 遍歷map結構,給空物件賦值
for([k,v] of mapVal){
obj[k] = v
}
return obj
}
let mObj = mapToObj(a3)
console.log(mObj); // {a: 100, b: 200}

如果有非字串鍵名,會被轉換成字串再創建物件鍵名
物件轉Map
let obj = {'a':123,'b':456}
let mObj2 = new Map(Object.entries(obj))
console.log(mObj2); // {'a' => 123, 'b' => 456}

Map轉JSON
Map轉JSON需要區分兩種情況
1、Map鍵名都是字串
2、Map鍵名有非字串的情況
1、Map鍵名都是字串
可以寫一個通用函式,用來將Map轉為JSON
let j = new Map()
.set('name','東方')
.set('text','不敗')
// mapToObj為上面創建的Map轉物件的函式
let shiftStrJson = (mapVal) => JSON.stringify(mapToObj(mapVal))
console.log(shiftStrJson(j)); // '{"name":"東方","text":"不敗"}'
2、Map鍵名有非字串的情況
function shiftMaptoArrayJson(mapVal){
return JSON.stringify([...mapVal])
}
let j2 = new Map()
.set('name','東方')
.set('text','不敗')
let shiftStrJson2 = shiftMaptoArrayJson(j2)
console.log(shiftStrJson2); // '[["name","東方"],["text","不敗"]]'
以上兩種的轉換結果:

JSON轉Map
JSON轉Map需要區分兩種情況
1、Map鍵名都是字串
2、Map鍵名有非字串的情況
1、鍵名都是字串
let strObj = '{"name":"東方","text":"不敗"}'
let strMap = new Map(Object.entries(JSON.parse(strObj)))
console.log(strMap); // {'name' => '東方', 'text' => '不敗'}
2、鍵名有非字串情況
let strObj2 = '[["name","東方"],["text","不敗"]]'
let strMap2 = new Map(JSON.parse(strObj2))
console.log(strMap2); // {'name' => '東方', 'text' => '不敗'}
案例原始碼:https://gitee.com/wang_fan_w/es6-science-institute
如果覺得這篇文章對你有幫助,歡迎點亮一下star喲
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/544636.html
標籤:JavaScript
上一篇:深入理解JavaScript物件
