Map
object holds key-value pairs and remembers the original insertion order of the keys.
Any value (both objects and
原语值
) may be used as either a key or a value.
Map
object iterates its elements in insertion order — a
for...of
loop returns an array of
[
key
,
value
]
for each iteration.
sameValueZero
algorithm.
NaN
is considered the same as
NaN
(even though
NaN !== NaN
) and all other values are considered equal according to the semantics of the
===
operator.
-0
and
+0
are considered equal, although this was not so in earlier drafts. See
"Value equality for -0 and 0"
在
浏览器兼容性
table for details.
Object
类似于
Map
—both let you set keys to values, retrieve those values, delete keys, and detect whether something is stored at a key. For this reason (and because there were no built-in alternatives),
Object
s have been used as
Map
s historically.
However, there are important differences that make
Map
preferable in certain cases:
| Map | Object | |
|---|---|---|
| Accidental Keys |
A
Map
does not contain any keys by default. It only contains what is explicitly put into it.
|
An
Object
has a prototype, so it contains default keys that could collide with your own keys if you're not careful.
注意:
As of ES5, this can be bypassed by using
|
| Key Types |
A
Map
's keys can be any value (including functions, objects, or any primitive).
|
The keys of an
Object
must be either a
String
或
Symbol
.
|
| Key Order |
The keys in
Map
are ordered. Thus, when iterating over it, a
Map
object returns keys in order of insertion.
|
The keys of an
Object
are not ordered.
注意:
Since ECMAScript 2015, objects
do
preserve creation order for string and
|
| Size |
The number of items in a
Map
is easily retrieved from its
size
特性。
|
The number of items in an
Object
must be determined manually.
|
| 迭代 |
A
Map
是
iterable
, so it can be directly iterated.
|
Iterating over an
Object
requires obtaining its keys in some fashion and iterating over them.
|
| Performance | Performs better in scenarios involving frequent additions and removals of key-value pairs. | Not optimized for frequent additions and removals of key-value pairs. |
Setting Object properties works for Map objects as well, and can cause considerable confusion.
Therefore, this appears to work in a way:
let wrongMap = new Map()
wrongMap['bla'] = 'blaa'
wrongMap['bla2'] = 'blaaa2'
console.log(wrongMap) // Map { bla: 'blaa', bla2: 'blaaa2' }
But that way of setting a property does not interact with the Map data structure. It uses the feature of the generic object. The value of 'bla' is not stored in the Map for queries. Other operations on the data fail:
wrongMap.has('bla') // false
wrongMap.delete('bla') // false
console.log(wrongMap) // Map { bla: 'blaa', bla2: 'blaaa2' }
The correct usage for storing data in the Map is through the
set(
key
,
value
)
方法。
let contacts = new Map()
contacts.set('Jessie', {phone: "213-555-1234", address: "123 N 1st Ave"})
contacts.has('Jessie') // true
contacts.get('Hilary') // undefined
contacts.set('Hilary', {phone: "617-555-4321", address: "321 S 2nd St"})
contacts.get('Jessie') // {phone: "213-555-1234", address: "123 N 1st Ave"}
contacts.delete('Raymond') // false
contacts.delete('Jessie') // true
console.log(contacts.size) // 1
Map()
Map
对象。
get Map[@@species]
The constructor function that is used to create derived objects.
Map.prototype.size
Map
对象。
Map.prototype.clear()
Map
对象。
Map.prototype.delete(
key
)
true
if an element in the
Map
object existed and has been removed, or
false
if the element does not exist.
Map.prototype.has(
key
)
will return
false
afterwards.
Map.prototype.get(
key
)
key
,或
undefined
若没有。
Map.prototype.has(
key
)
key
在
Map
object or not.
Map.prototype.set(
key
,
value
)
value
为
key
在
Map
object. Returns the
Map
对象。
Map.prototype[@@iterator]()
Iterator
object that contains
an array of
[
key
,
value
]
for each element in the
Map
object in insertion order.
Map.prototype.keys()
Iterator
object that contains the
keys
for each element in the
Map
object in insertion order.
Map.prototype.values()
Iterator
object that contains the
值
for each element in the
Map
object in insertion order.
Map.prototype.entries()
Iterator
object that contains
an array of
[
key
,
value
]
for each element in the
Map
object in insertion order.
Map.prototype.forEach(
callbackFn
[,
thisArg
])
callbackFn
once for each key-value pair present in the
Map
object, in insertion order. If a
thisArg
parameter is provided to
forEach
, it will be used as the
this
value for each callback.
let myMap = new Map()
let keyString = 'a string'
let keyObj = {}
let 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
can also be used as a key. Even though every
NaN
is not equal to itself (
NaN !== NaN
is true), the following example works because
NaN
s are indistinguishable from each other:
let myMap = new Map()
myMap.set(NaN, 'not a number')
myMap.get(NaN)
// "not a number"
let otherNaN = Number('foo')
myMap.get(otherNaN)
// "not a number"
Maps can be iterated using a
for..of
循环:
let myMap = new Map()
myMap.set(0, 'zero')
myMap.set(1, 'one')
for (let [key, value] of myMap) {
console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one
for (let key of myMap.keys()) {
console.log(key)
}
// 0
// 1
for (let value of myMap.values()) {
console.log(value)
}
// zero
// one
for (let [key, value] of myMap.entries()) {
console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one
Maps can be iterated using the
forEach()
method:
myMap.forEach(function(value, key) {
console.log(key + ' = ' + value)
})
// 0 = zero
// 1 = one
let kvArray = [['key1', 'value1'], ['key2', 'value2']]
// Use the regular Map constructor to transform a 2D key-value Array into a map
let myMap = new Map(kvArray)
myMap.get('key1') // returns "value1"
// Use Array.from() to transform a map into a 2D key-value Array
console.log(Array.from(myMap)) // Will show you exactly the same Array as kvArray
// A succinct way to do the same, using the spread syntax
console.log([...myMap])
// Or use the keys() or values() iterators, and convert them to an array
console.log(Array.from(myMap.keys())) // ["key1", "key2"]
就像
Array
s,
Map
s can be cloned:
let original = new Map([ [1, 'one'] ]) let clone = new Map(original) console.log(clone.get(1)) // one console.log(original === clone) // false (useful for shallow comparison)
Important: Keep in mind that the data itself is not cloned.
Maps can be merged, maintaining key uniqueness:
let first = new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]) let second = new Map([ [1, 'uno'], [2, 'dos'] ]) // Merge two maps. The last repeated key wins. // Spread operator essentially converts a Map to an Array let merged = new Map([...first, ...second]) console.log(merged.get(1)) // uno console.log(merged.get(2)) // dos console.log(merged.get(3)) // three
Maps can be merged with Arrays, too:
let first = new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]) let second = new Map([ [1, 'uno'], [2, 'dos'] ]) // Merge maps with an array. The last repeated key wins. let 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
| 规范 |
|---|
|
ECMAScript (ECMA-262)
在该规范中的 Map 定义。 |
| Desktop | Mobile | Server | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Map
|
Chrome 38 | Edge 12 | Firefox 13 | IE 11 | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 14 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 |
nodejs
0.12
|
Map()
构造函数
|
Chrome 38 | Edge 12 | Firefox 13 | IE 11 | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 14 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 |
nodejs
0.12
|
clear
|
Chrome 38 | Edge 12 | Firefox 19 | IE 11 | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 19 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 | nodejs 0.12 |
delete
|
Chrome 38 | Edge 12 | Firefox 13 | IE 11 | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 14 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 |
nodejs
0.12
|
entries
|
Chrome 38 | Edge 12 | Firefox 20 | IE No | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 20 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 | nodejs 0.12 |
forEach
|
Chrome 38 | Edge 12 | Firefox 25 | IE 11 | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 25 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 | nodejs 0.12 |
get
|
Chrome 38 | Edge 12 | Firefox 13 | IE 11 | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 14 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 |
nodejs
0.12
|
has
|
Chrome 38 | Edge 12 | Firefox 13 | IE 11 | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 14 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 |
nodejs
0.12
|
| Key equality for -0 and 0 | Chrome 38 | Edge 12 | Firefox 29 | IE No | Opera 25 | Safari 9 | WebView Android 38 | Chrome Android 38 | Firefox Android 29 | Opera Android 25 | Safari iOS 9 | Samsung Internet Android 3.0 | nodejs 4.0.0 |
keys
|
Chrome 38 | Edge 12 | Firefox 20 | IE No | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 20 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 | nodejs 0.12 |
set
|
Chrome 38 | Edge 12 | Firefox 13 |
IE
部分支持
11
|
Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 14 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 |
nodejs
0.12
|
size
|
Chrome 38 | Edge 12 |
Firefox
19
|
IE 11 | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 |
Firefox Android
19
|
Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 | nodejs 0.12 |
值
|
Chrome 38 | Edge 12 | Firefox 20 | IE No | Opera 25 | Safari 8 | WebView Android 38 | Chrome Android 38 | Firefox Android 20 | Opera Android 25 | Safari iOS 8 | Samsung Internet Android 3.0 | nodejs 0.12 |
@@iterator
|
Chrome 43 | Edge 12 |
Firefox
36
|
IE No | Opera 30 | Safari 10 | WebView Android 43 | Chrome Android 43 |
Firefox Android
36
|
Opera Android 30 | Safari iOS 10 | Samsung Internet Android 4.0 | nodejs 0.12 |
@@species
|
Chrome 51 | Edge 13 | Firefox 41 | IE No | Opera 38 | Safari 10 | WebView Android 51 | Chrome Android 51 | Firefox Android 41 | Opera Android 41 | Safari iOS 10 | Samsung Internet Android 5.0 |
nodejs
6.5.0
|
@@toStringTag
|
Chrome 44 | Edge 79 | Firefox 51 | IE No | Opera No | Safari No | WebView Android 44 | Chrome Android 44 | Firefox Android 51 | Opera Android No | Safari iOS No | Samsung Internet Android 4.0 | nodejs 6.0.0 |
完整支持
部分支持
不支持
见实现注意事项。
用户必须明确启用此特征。
使用非标名称。
Map
Function
Object
Object.prototype.__defineGetter__()
Object.prototype.__defineSetter__()
Object.prototype.__lookupGetter__()
Object.prototype.__lookupSetter__()
Object.prototype.hasOwnProperty()
Object.prototype.isPrototypeOf()
Object.prototype.propertyIsEnumerable()
Object.prototype.toLocaleString()
Object.prototype.toSource()
Object.prototype.toString()
Object.prototype.valueOf()
Object.setPrototypeOf()