Map
Map
Map
对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
语法
new Map([iterable])
参数
iterable
Iterable 可以是一个数组或者其他 iterable
对象,其元素或为键值对,或为两个元素的数组。 每个键值对都会添加到新的 Map。null
会被当做 undefined。
描述
一个Map对象以插入顺序迭代其元素 — 一个 for...of
循环为每次迭代返回一个[key,value]数组。
应该注意的是,Map
是一个对象的映射,将只映射到对象的插入顺序 - 这是随机的,而不是依照次序的。
键的相等(Key equality)
键的比较是基于 "SameValueZero" 算法:NaN
是与 NaN
相同的(虽然 NaN !== NaN
),剩下所有其它的值是根据 === 运算符的结果判断是否相等。在目前的ECMAScript规范中,-0
和+0
被认为是相等的,尽管这在早期的草案中并不是这样。有关详细信息,请参阅浏览器兼容性 表中的“value equality for -0
and 0”。
Objects 和 maps 的比较
Object
和 Map类似
的一点是,它们都允许你按键存取一个值,都可以删除键,还可以检测一个键是否绑定了值.因此,一直以来,我们都把对象当成Map
来使用,不过,现在有了Map,下面的区别解释了为什么
使用Map更好
点.
- 一个
对象通常都有自己的原型
,所以一个对象总有一个"prototype"键。不过,从 ES5 开始可以使用map = Object.create(null)
来创建一个没有原型的对象。
- 一个对象的键只能是
字符串
或者Symbols
,但一个Map 的键可以是任意值。
- 你可以通过size属性很容易地得到一个
Map的键值对个数,
而对象的键值对个数只能手动确认。
但是这并不意味着你可以随意使用 Map
,对象仍旧是最常用的。如果你不确定要使用哪个,请思考下面的问题:
- 在运行之前 key 是否是未知的,是否需要动态地查询 key 呢?
- 是否所有的值都是统一类型,这些值可以互换么?
- 是否需要不是字符串类型的 key ?
- 键值对经常增加或者删除么?
- 是否有任意个且非常容易改变的键值对?
- 这个集合可以遍历么?
假如以上全是“是”的话,那么你需要用 Map
来保存这个集。 相反,你有固定数目的键值对,独立操作它们,区分它们的用法,那么你需要的是对象。
属性
Map.length
属性 length 的值为 0 。get Map[@@species]
本构造函数用于创建派生对象。Map.prototype
表示 Map
构造器的原型。 允许添加属性从而应用于所有的 Map
对象。
Map示例
所有的 Map
对象实例都会继承Map.prototype
。
属性
Map.prototype.constructor
返回一个函数,它创建了实例的原型。默认是Map
函数。Map.prototype.size
返回Map
对象的键/值对的数量。
方法
Map.prototype.clear()
移除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作为映射的键
NaN
也可以作为Map对象的键. 虽然NaN
和任何值甚至和自己都不相等(NaN !== NaN
返回true), 但下面的例子表明,两个NaN
作为Map的键来说是没有区别的:
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方法迭代映射
映射也可以使用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()方法迭代映射
映射也可以通过forEach()
方法迭代:
myMap.forEach(function(value, key) {
console.log(key + ' = ' + value
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"
映射与数组对象的关系
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"]
规范
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262)The definition of 'Map' in that specification. | Standard | Initial definition. |
ECMAScript Latest Draft (ECMA-262)The definition of 'Map' in that specification. | Living Standard | |
浏览器兼容性
Feature | Chrome | Edge | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
Basic support | 38 1 | 12 | 13 (13) | 11 | 25 | 7.1 |
Constructor argument: new Map(iterable) | 38 | 12 | 13 (13) | No support | 25 | 9 |
Map.clear() | 31 38 | 12 | 19 (19) | 11 | 25 | 7.1 |
Map.keys(), Map.values(), Map.entries() | 37 38 | 12 | 20 (20) | No support | 25 | 7.1 |
Map.forEach() | 36 38 | 12 | 25 (25) | 11 | 25 | 7.1 |
Key equality for -0 and 0 | 34 38 | 12 | 29 (29) | No support | 25 | 9 |
Constructor argument: new Map(null) | (Yes) | 12 | 37 (37) | 11 | (Yes) | 9 |
Map@@species | 51 | 13 | 41 (41) | No support | 38 | 10 |
Map() without new throws | (Yes) | 12 | 42 (42) | 11 | (Yes) | 9 |
Feature | Android | Chrome for Android | Edge | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|---|
Basic support | No support | 38 1 | (Yes) | 13.0 (13) | No support | No support | 8 |
Constructor argument: new Map(iterable) | No support | 38 | (Yes) | 13.0 (13) | No support | No support | 9 |
Map.clear() | No support | 31 38 | (Yes) | 19.0 (19) | No support | No support | 8 |
Map.keys(), Map.values(), Map.entries() | No support | 37 38 | (Yes) | 20.0 (20) | No support | No support | 8 |
Map.forEach() | No support | 36 38 | (Yes) | 25.0 (25) | No support | No support | 8 |
Key equality for -0 and 0 | No support | 34 38 | (Yes) | 29.0 (29) | No support | No support | No support |
Constructor argument: new Map(null) | ? | (Yes) | (Yes) | 37.0 (37) | ? | ? | 9 |
Map@@species | ? | ? | (Yes) | 41.0 (41) | ? | ? | 10 |
Map() without new throws | 5.1 | ? | (Yes) | 42.0 (42) | ? | ? | 9 |