Map
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
Map
是保存了鍵值對(key-value pairs)的物件。任何值(包括物件及基本型別(primitive)值)都可以作為鍵或值。
語法
new Map([iterable])
參數
描述
一個 Map
物件會根據元素的新增順序走訪自身的所有元素 — for...of
迴圈會在每次迭代回傳一個 [key, value]
陣列。
鍵的相等性
鍵相等是基於 SameValueZero 的演算法:NaN
被認為與 NaN
相同(即使 NaN !== NaN
)並且根據 ===
運算符的語義,所有其他值都被認為相等。在目前的 ECMAScript 規範中,-0
和 +0
被認為是相等的,儘管在早期的草案中並非如此。詳細的內容請參閱 瀏覽器相容性 表中的 "Value equality for -0 and 0"。
Object 及 Map 的比較
Object
和 Map
類似。兩者都允許你設置對應的鍵值對,檢索這些值,刪除鍵,並檢測是否有什麼存儲在鍵中。正因為如此(也因為沒有內置的替代品),Object
在歷史上一直被當作 Map
使用;然而在某些情況下,使用 Map
有一些重要的不同之處:
Object
的鍵是字串
和Symbol
,而它們在Map
中可以是任意的資料型態,包括函數,對象以及原始的資料型態。- 你可以使用
size
屬性輕鬆地獲得Map
的大小,而Object
中的屬性數量必須手動確認。 Map
是可迭代(iterable)的,因此可以直接迭代,而在Object
上迭代則需要以某種方式獲取其鍵並對其進行迭代。Object
有一個原型,所以如果不小心,映射中有一些默認鍵可能與鍵發生衝突。從 ES5 開始,這可以通過使用map = Object.create(null)
來繞過這個問題,但是很少這樣做。- 在涉及頻繁添加和刪除鍵值對的場景中,
Map
可能表現得更好。
屬性
Map.length
-
length
屬性的值為 0 要計算Map
中有多少元素,可以使用Map.prototype.size
。 Map[Symbol.species]
-
用於創建派生物件的構造函數。
Map.prototype
-
表示
Map
構造函數的原型,允許對所有的Map
物件添加屬性
Map
物件實體
所有的 Map
實例都繼承自 Map.prototype
.
屬性
Map.prototype[Symbol.toStringTag]
-
The initial value of the
Symbol.toStringTag
property is the string"Map"
. This property is used inObject.prototype.toString()
. Map.prototype.size
-
Returns the number of key/value pairs in the
Map
object.
方法
Map.prototype.clear()
-
Removes all key-value pairs from the
Map
object. Map.prototype.delete()
-
Returns
true
if an element in theMap
object existed and has been removed, orfalse
if the element does not exist.map.has(key)
will returnfalse
afterwards. Map.prototype.get()
-
Returns the value associated to the passed key, or
undefined
if there is none. Map.prototype.has()
-
Returns a boolean indicating whether a value has been associated with the passed key in the
Map
object or not. Map.prototype.set()
-
Sets the value for the passed key in the
Map
object. Returns theMap
object. Map.prototype[Symbol.iterator]()
-
Returns a new Iterator object that contains a two-member array of
[key, value]
for each element in theMap
object in insertion order. Map.prototype.keys()
-
Returns a new Iterator object that contains the keys for each element in the
Map
object in insertion order. Map.prototype.values()
-
Returns a new Iterator object that contains the values for each element in the
Map
object in insertion order. Map.prototype.entries()
-
Returns a new Iterator object that contains a two-member array of
[key, value]
for each element in theMap
object in insertion order. Map.prototype.forEach()
-
Calls
callbackFn
once for each key-value pair present in theMap
object, in insertion order. If athisArg
parameter is provided toforEach
, it will be used as thethis
value for each callback.
範例
使用 Map
物件
var myMap = new Map();
var keyString = "a string",
keyObj = {},
keyFunc = function () {};
// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");
myMap.size; // 3
// getting the values
myMap.get(keyString); // "value associated with 'a string'"
myMap.get(keyObj); // "value associated with keyObj"
myMap.get(keyFunc); // "value associated with keyFunc"
myMap.get("a string"); // "value associated with 'a string'"
// because keyString === 'a string'
myMap.get({}); // undefined, because keyObj !== {}
myMap.get(function () {}); // undefined, because keyFunc !== function () {}
使用 NaN
作為 Map
的鍵
NaN
同樣可以作為 Map
的 key,雖然每個 NaN
都不等於自己本身,下面的例子是有效的,因為 NaN
無法區分彼此。
var myMap = new Map();
myMap.set(NaN, "not a number");
myMap.get(NaN); // "not a number"
var otherNaN = Number("foo");
myMap.get(otherNaN); // "not a number"
透過 for..of
迭代 Map
Map 可以使用 for..of
迴圈進行迭代:
var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
console.log(key + " = " + value);
}
// 0 = zero
// 1 = one
for (var key of myMap.keys()) {
console.log(key);
}
// 0
// 1
for (var value of myMap.values()) {
console.log(value);
}
// zero
// one
for (var [key, value] of myMap.entries()) {
console.log(key + " = " + value);
}
// 0 = zero
// 1 = one
透過 forEach()
迭代 Map
Map
可以使用 forEach()
方法進行迭代:
myMap.forEach(function (value, key) {
console.log(key + " = " + value);
});
// Will show 2 logs; first with "0 = zero" and second with "1 = one"
與 Array
物件關聯
var kvArray = [
["key1", "value1"],
["key2", "value2"],
];
// Use the regular Map constructor to transform a 2D key-value Array into a map
var myMap = new Map(kvArray);
myMap.get("key1"); // returns "value1"
// Use the Array.from function to transform a map into a 2D key-value Array
console.log(Array.from(myMap)); // Will show you exactly the same Array as kvArray
// Or use the keys or values iterators and convert them to an array
console.log(Array.from(myMap.keys())); // Will show ["key1", "key2"]
複製與合併 Map
就像 Array
一樣,Map
可以被複製:
var original = new Map([[1, "one"]]);
var clone = new Map(original);
console.log(clone.get(1)); // one
console.log(original === clone); // false. Useful for shallow comparison
請記住,數據本身並非克隆的。
Map
可以被合併,保持鍵的唯一性:
var first = new Map([
[1, "one"],
[2, "two"],
[3, "three"],
]);
var second = new Map([
[1, "uno"],
[2, "dos"],
]);
// Merge two maps. The last repeated key wins.
// Spread operator essentially converts a Map to an Array
var merged = new Map([...first, ...second]);
console.log(merged.get(1)); // uno
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
Map
也可以跟 Array
合併:
var first = new Map([
[1, "one"],
[2, "two"],
[3, "three"],
]);
var second = new Map([
[1, "uno"],
[2, "dos"],
]);
// Merge maps with an array. The last repeated key wins.
var merged = new Map([...first, ...second, [1, "eins"]]);
console.log(merged.get(1)); // eins
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
規格
Specification |
---|
ECMAScript Language Specification # sec-map-objects |
瀏覽器相容性
BCD tables only load in the browser