1. 程式人生 > >es6中的map

es6中的map

 

含義:

Map的提出為了解決js中object(物件=>{key:value})中鍵(key)只能是字串的限制,Map的鍵(key)可以是各種型別的值(包括物件)都可以當作鍵(key),包括es6提出的SetMap都可以用來生成新的 Map。

const m = new Map();

(1)如果對同一個鍵多次賦值,後面的值將覆蓋前面的值。

(2)如果讀取一個未知的鍵,則返回undefined

注意,只有對同一個物件的引用,Map 結構才將其視為同一個鍵。這一點要非常小心。(可以理解為,用物件名來新增或者獲取,不要用物件的例項來新增獲取)

例:

const map = new Map();

map.set(['a'], 555);
map.get(['a']) // undefined


const k1 = ['a'];
const k2 = ['a'];

map
.set(k1, 111)
.set(k2, 222);

map.get(k1) // 111
map.get(k2) // 222

Map 的鍵實際上是跟記憶體地址繫結的,只要記憶體地址不一樣,就視為兩個鍵。這就解決了同名屬性碰撞(clash)的問題,我們擴充套件別人的庫的時候,如果使用物件作為鍵名,就不用擔心自己的屬性與原作者的屬性同名。在Map中0-0就是一個鍵,布林值true

和字串true則是兩個不同的鍵。另外,undefinednull也是兩個不同的鍵。雖然NaN不嚴格相等於自身,但 Map 將其視為同一個鍵。

屬性和操作方法

(1)size 屬性size屬性返回 Map 結構的成員總數

(2)set(key, value):set方法設定鍵名key對應的鍵值為value,然後返回整個 Map 結構。如果key已經有值,則鍵值會被更                                          新,否則就新生成該鍵。(set

方法返回的是當前的Map物件,因此可以採用鏈式寫法。)

let map = new Map()
  .set(1, 'a')
  .set(2, 'b')
  .set(3, 'c');

(3)get(key):get方法讀取key對應的鍵值,如果找不到key,返回undefined

(4)has(key):has方法返回一個布林值,表示某個鍵是否在當前 Map 物件之中。

(5)delete(key):delete方法刪除某個鍵,返回true。如果刪除失敗,返回false

(6)clear():clear方法清除所有成員,沒有返回值。

遍歷方法

  • keys():返回鍵名的遍歷器。
  • values():返回鍵值的遍歷器。
  • entries():返回所有成員的遍歷器。
  • forEach():遍歷 Map 的所有成員。

注意: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"

Map 結構轉為陣列結構,比較快速的方法是使用擴充套件運算子(...)。

const map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

[...map.keys()]
// [1, 2, 3]

[...map.values()]
// ['one', 'two', 'three']

[...map.entries()]
// [[1,'one'], [2, 'two'], [3, 'three']]

[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]

結合陣列的map方法、filter方法,可以實現 Map 的遍歷和過濾(Map 本身沒有mapfilter方法)。

const map0 = new Map()
  .set(1, 'a')
  .set(2, 'b')
  .set(3, 'c');

const map1 = new Map(
  [...map0].filter(([k, v]) => k < 3)
);
// 產生 Map 結構 {1 => 'a', 2 => 'b'}

const map2 = new Map(
  [...map0].map(([k, v]) => [k * 2, '_' + v])
    );
// 產生 Map 結構 {2 => '_a', 4 => '_b', 6 => '_c'}

 此外,Map 還有一個forEach方法,與陣列的forEach方法類似,也可以實現遍歷。

const reporter = {
  report: function(key, value) {
    console.log("Key: %s, Value: %s", key, value);
  }
};

map.forEach(function(value, key, map) {
  this.report(key, value);
}, reporter);

上面程式碼中,forEach方法的回撥函式的this,就指向reporter

結構轉換

(1)Map 轉為陣列:...

 

const myMap = new Map()
  .set(true, 7)
  .set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]

(2)陣列 轉為 Map:將陣列寫入 Map 建構函式

new Map([
  [true, 7],
  [{foo: 3}, ['abc']]
])
// Map {
//   true => 7,
//   Object {foo: 3} => ['abc']
// }

(3)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 }

(4)物件轉為 Map:

 

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}

(5)Map 轉為 JSON

Map 轉為 JSON 要區分兩種情況。一種情況是,Map 的鍵名都是字串,這時可以選擇轉為物件 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。

unction mapToArrayJson(map) {
  return JSON.stringify([...map]);
}

let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
mapToArrayJson(myMap)
// '[[true,7],[{"foo":3},["abc"]]]'

(6)JSON 轉為 Map

JSON 轉為 Map,正常情況下,所有鍵名都是字串。

function jsonToStrMap(jsonStr) {
  return objToStrMap(JSON.parse(jsonStr));
}

jsonToStrMap('{"yes": true, "no": false}')
// Map {'yes' => true, 'no' => false}

但是,有一種特殊情況,整個 JSON 就是一個數組,且每個陣列成員本身,又是一個有兩個成員的陣列。這時,它可以一一對應地轉為 Map。這往往是 Map 轉為陣列 JSON 的逆操作。

function jsonToMap(jsonStr) {
  return new Map(JSON.parse(jsonStr));
}

jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
// Map {true => 7, Object {foo: 3} => ['abc']}