The Map
object is used to store key-value pairs and can remember the original insertion order of the keys. Any object or primitive value can be used as a key or value.
The WeakMap
object is also used to store key-value pairs, with the key being a weak reference and must be an object, while the value can be any object or primitive value.
The Map
object is similar to a regular key-value pair Object
object, also a collection of key-value pairs, but there are some important differences between them:
Description | Map | Object |
---|---|---|
Unexpected keys | By default, a Map does not contain any keys, only the keys that have been explicitly inserted. |
An Object has a prototype, and the keys on the prototype chain may conflict with the keys set on the object. |
Key types | A key of a Map can be any value, including functions, objects, or any primitive type. |
The keys of an Object must be a String or Symbol . |
Key order | The key in a Map is ordered, when iterated, a Map object returns keys and values in the insertion order. |
The iteration order of keys in an Object depends on the type of the key and the order of creation. |
Number of key-value pairs | The number of key-value pairs in a Map can be easily obtained through the size property. |
The number of key-value pairs in an Object can only be calculated manually. |
Iteration | Map is iterable , so it can be directly iterated. |
Iterating an Object requires obtaining its keys in some way before iterating. |
Performance | Map performs better in scenarios where keys and values are frequently added or removed. |
Object is unoptimized for scenarios with frequent additions and deletions of key-value pairs. |
Note: Regarding the iteration order of keys in an Object
, since ES6
, objects retain the creation order of String
and Symbol
. When the created object only has String
or Symbol
, the iteration order is the same as the creation order. When both types exist in the object, String
always comes first. When String
can be converted to a Number
, these keys are at the forefront during iteration, and they are iterated in numeric order.
Map.prototype.constructor
: Returns the constructor function.Map.prototype.size
: Returns the number of key-value pairs in theMap
object.Map.prototype.clear()
: Removes all key-value pairs from theMap
object.Map.prototype.delete(key)
: Removes the element from theMap
object if it exists and returnstrue
; otherwise, returnsfalse
if the element does not exist.Map.prototype.entries()
: Returns a newIterator
object that includes the[key, value]
array of each element in theMap
object in insertion order.Map.prototype.forEach(callback[, thisArg])
: Invokes thecallback
function once for each key-value pair in theMap
object in insertion order. IfthisArg
is provided forforEach
, it will be used as thethis
value for each callback.Map.prototype.get(key)
: Returns the value corresponding to the key, orundefined
if it does not exist.Map.prototype.has(key)
: Returns a Boolean indicating whether theMap
instance contains the value corresponding to the key.Map.prototype.keys()
: Returns a newIterator
object that includes the keys of each element in theMap
object in insertion order.Map.prototype.set(key, value)
: Sets the value of the key in theMap
object and returns theMap
object.Map.prototype.values()
: Returns a newIterator
object that includes the values of each element in theMap
object in insertion order.Map.prototype[@@iterator]()
: Returns a newIterator
object that includes the[key, value]
array of each element in theMap
object in insertion order.
var m = new Map();
var stringKey = "s";
var objectKey = {};
m.set(stringKey, "stringValue");
m.set(objectKey, "objectValue");
console.log(m.size); // 2
console.log(m.get(stringKey)); // stringValue
console.log(m.get(objectKey)); // objectValue
for (let [key, value] of m) {
console.log(key, value);
}
/*
s stringValue
{} objectValue
*/
var m2 = new Map([
["stringKey", "stringValue"],
[{}, "objectValue"]
]);
console.log(m2); // Map(2) {"stringKey" => "stringValue", {…} => "objectValue"}
var m3 = new Map([
...m,
...m2,
["stringKey", "coverStringValue"],
[{}, "{} !== {}"],
[NaN, "NaN !== NaN But key(NaN) === key(NaN)"],
[NaN, "NaN !== NaN But key(NaN) === key(NaN)"],
]);
console.log(m3); // Map(6) {"s" => "stringValue", {…} => "objectValue", "stringKey" => "coverStringValue", {…} => "objectValue", {…} => "{} !== {}", NaN => "NaN !== NaN But key(NaN) === key(NaN)"}
The key
of WeakMap
can only be of type Object
, primitive data types cannot be used as key
. The WeakMap
holds a weak reference to each key object, which means that garbage collection can be done correctly when there are no other references. The key
used for mapping in WeakMap
is only valid when it has not been collected. Due to the weak reference, the key
of WeakMap
cannot be enumerated, and there is no method to retrieve all the key
s.
In simple terms, sometimes it is necessary to store some objects on a particular object, but this will create a reference to that object. Once that object is no longer needed, we must manually remove that reference, otherwise the garbage collection mechanism cannot release the memory occupied by the object. The design of WeakMap
is to solve this problem. The objects referenced by its keys are all weak references, and the garbage collection mechanism does not consider those references, so as long as the other references to the referenced object are cleared, the garbage collection mechanism will release the memory occupied by the object. At this time, the corresponding key-value pairs in WeakMap
will disappear, and there is no need to manually delete the reference. If you need to add objects to an object without interfering with the garbage collection mechanism, you can use WeakMap
.
WeakMap.prototype.constructor
: Returns the constructor.WeakMap.prototype.delete(key)
: Removes the associated object ofkey
.WeakMap.prototype.get(key)
: Returns the associated object ofkey
, and returnsundefined
if there is no associated object forkey
.WeakMap.prototype.has(key)
: Returns aBoolean
value indicating whether there is an associated object forkey
.WeakMap.prototype.set(key, value)
: Sets a group of key-value pairs in theWeakMap
and returns theWeakMap
object.
// WeakMap example code
var wm = new WeakMap();
var key = {};
wm.set(key, new Array(6 * 1024 * 1024)); // Store a large array
console.log(wm.get(key)); // (6291456) [empty × 6291456]
key = null;
console.log(wm.get(key)); // undefined
// WeakMap memory recycling example
/** node --expose-gc **/ // Start the node environment and manually invoke the garbage collection mechanism
global.gc(); // First, trigger the garbage collection
process.memoryUsage(); // View memory usage, heapUsed about 2M
/*
{
rss: 21975040,
heapTotal: 4608000,
heapUsed: 2454040,
external: 1384318
}
*/
var wm = new WeakMap();
var key = {};
wm.set(key, new Array(6 * 1024 * 1024)); // Store a large array
console.log(wm.get(key)); // (6291456) [empty × 6291456]
process.memoryUsage(); // heapUsed about 53M
/*
{
rss: 73420800,
heapTotal: 55259136,
heapUsed: 53060600,
external: 1384408
}
*/
global.gc(); // Manually trigger garbage collection
process.memoryUsage(); // heapUsed about 53M
/*
{
rss: 73302016,
heapTotal: 55259136,
heapUsed: 52637112,
external: 1384350
}
*/
key = null; // Release reference
global.gc(); // Trigger garbage collection
process.memoryUsage(); // heapUsed about 2M, memory recycled
/*
{
rss: 23142400,
heapTotal: 4923392,
heapUsed: 2674536,
external: 1384445
}
*/
console.log(wm.get(key)); // undefined
// Map example code for comparison
var m = new Map();
var key = {};
m.set(key, new Array(6 * 1024 * 1024)); // Store a large array
console.log(m.get(key)); // (6291456) [empty × 6291456]
key = null;
console.log(m.get(key)); // undefined
console.log(m); // Map(1) {{…} => Array(6291456)}
m.clear(); // Recycle memory
console.log(m); // Map(0) {}
// Map memory recycling example for comparison
/** node --expose-gc **/ // Start the node environment and manually invoke the garbage collection mechanism
global.gc(); // First, trigger the garbage collection
process.memoryUsage(); // View memory usage, heapUsed about 2M
/*
{
rss: 21856256,
heapTotal: 4608000,
heapUsed: 2460600,
external: 1384318
}
*/
var m = new Map();
var key = {};
m.set(key, new Array(6 * 1024 * 1024)); // Store a large array
console.log(m.get(key)); // (6291456) [empty × 6291456]
process.memoryUsage(); // heapUsed about 53M
/*
{
rss: 73744384,
heapTotal: 55521280,
heapUsed: 53703816,
external: 1384504
}
*/
global.gc(); // Manually trigger garbage collection
process.memoryUsage(); // heapUsed about 53M
/*
{
rss: 73125888,
heapTotal: 55521280,
heapUsed: 53135936,
external: 1384350
}
*/
key = null; // Release reference
global.gc(); // Trigger garbage collection
process.memoryUsage(); // heapUsed about 53M, memory not recycled
/*
{
rss: 73093120,
heapTotal: 55521280,
heapUsed: 52960672,
external: 1384350
}
*/
console.log(m.get(key)); // undefined // This is undefined because the key value has changed, but in this Map instance object, the {} => Array key-value pair still exists, and it's a strong reference, so memory is not recycled
console.log(m); // Map(1) {{…} => Array(6291456)}
m.clear(); // Recycle memory
global.gc(); // Trigger garbage collection
process.memoryUsage(); // heapUsed about 2M, memory recycled
/*
{
rss: 22908928,
heapTotal: 5185536,
heapUsed: 2627064,
external: 1384350
}
*/
console.log(m); // Map(0) {}
https://github.com/WindrunnerMax/EveryDay
https://blog.csdn.net/c__dreamer/article/details/82182649
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/WeakMap