Difference analysis of Object map and weakmap in JavaScript

  • 2021-10-13 06:38:39
  • OfStack

Preface

Before ECMAScript 6, implementing "key/value" storage in JavaScript can be done conveniently and efficiently by using Object, that is, using object attributes as keys and then using attributes to reference values. However, this implementation is not without problems, so the TC39 Committee has defined a specification for "key/value" storage. As a new feature of ECMAScript 6, Map is a new collection type that brings true key/value storage to the language. Most of the features of the Map can be implemented with the Object type, but there are some subtle differences between the two. Which one is used in practice is worth carefully screening.

1. Use of map

Initialization

object can be created using literals, constructors, Object. crate. map can only be created with new keywords and constructors. For map, if you want to initialize the instance at the same time of creation, you can pass an iterable object to the Map constructor, which needs to contain an array of key/value pairs. Each key/value pair in the iterative object is inserted into the new mapping instance in iterative order:


object  How to create the 
 
const object = {}
const object1 = new Object()
const object2 = Object.create({})
 
map  How to create the 
// Use new Keyword 
const m0 = new Map;
//  Initialize a map with a nested array 
const m1 = new Map([
 ["key1", "val1"],
 ["key2", "val2"],
 ["key3", "val3"]
]);
alert(m1.size); // 3
//  Initialize the map using a custom iterator 
const m2 = new Map({
[Symbol.iterator]: function*() {
 yield ["key1", "val1"];
 yield ["key2", "val2"];
 yield ["key3", "val3"];
}
});
alert(m2.size); // 3
//  Mapping Expected Keys / Value pairs, whether or not provided 
const m3 = new Map([[]]);
alert(m3.has(undefined)); // true
alert(m3.get(undefined)); // undefined

map key type

Unlike Object, which can only use numeric values, strings, or symbols as keys, Map can use any JavaScript data type as a key. Map uses SameValueZero comparison operation internally (ECMAScript specification, which cannot be used in language), which is basically equivalent to using strict object equality standard to check key matching. Similar to Object, the value of the map is unlimited.


 const m = new Map();
 const functionKey = function() {};
 const symbolKey = Symbol();
 const objectKey = new Object();
 m.set(functionKey, "functionValue");
 m.set(symbolKey, "symbolValue");
 m.set(objectKey, "objectValue");
 alert(m.get(functionKey)); // functionValue
 alert(m.get(symbolKey)); // symbolValue
 alert(m.get(objectKey)); // objectValue
 // SameValueZero Comparison means that independent instances do not conflict 
 alert(m.get(function() {})); // undefined
  

Sequence and iteration

One major difference from the Object type is that the Map instance maintains the insertion order of key-value pairs, so iterative operations can be performed based on the insertion order. A mapping instance can provide an iterator (Iterator) that generates arrays in the form of [key, value] in insertion order. This iterator can be obtained through the entries () method (or the Symbol. iterator attribute, which references entries ()):


const m = new Map([
 ["key1", "val1"],
 ["key2", "val2"],
 ["key3", "val3"]
]);
alert(m.entries === m[Symbol.iterator]); // true
for (let pair of m.entries()) {
 alert(pair);
}
// [key1,val1]
// [key2,val2]
// [key3,val3]
for (let pair of m[Symbol.iterator]()) {
 alert(pair);
}
// [key1,val1]
// [key2,val2]
// [key3,val3]

2. Choose Object or Map

For most Web development tasks, choosing Object or Map is only a matter of personal preference, which has little impact. However, for developers who care about memory and performance, there are significant differences between objects and mappings.

1. Memory usage

The engineering-level implementations of Object and Map vary significantly from browser to browser, but the amount of memory required to store a single key/value pair increases linearly with the number of keys. Bulk addition or removal of key/value pairs depends on the engineering implementation of each browser's memory allocation for that type. The situation varies from browser to browser, but given a fixed memory size, Map can store about 50% more key/value pairs than Object.

2. Insertion performance

Inserting a new key/value pair into Object and Map consumes roughly the same amount, but inserting Map is a little faster than 1 in all browsers. For these two types, the insertion speed does not increase linearly with the number of key/value pairs. If the code involves a large number of inserts, it is obvious that Map performs better.

3. Find speed

Unlike insertion, the performance difference between finding key/value pairs from large Object and Map is minimal, but Object is sometimes faster if only a small number of key/value pairs are included. In the case of using Object as an array (for example, using contiguous integers as attributes), the browser engine can be optimized to use a more efficient layout in memory. This is impossible for Map. For these two types, the lookup speed does not increase linearly with the number of key/value pairs. If the code involves a large number of lookup operations, it may be better to choose Object in some cases.

4. Remove performance

Performance 1 for removing Object attributes using delete has been criticized for a long time, and it is still the case in many browsers. For this reason, there are a number of pseudo-deletions of object attributes, including setting the attribute value to undefined or null. But most of the time, this is an annoying or inappropriate compromise. For most browser engines, the delete () operation of Map is faster than insert and find. If the code involves a large number of deletions, there is no doubt that Map should be selected

3. weakMap

ECMAScript 6's new "Weak Mapping" (WeakMap) is a new set type that brings enhanced key/value pair storage to the language. WeakMap is a "sibling" type of Map, and its API is also a subset of Map. "weak" (weak) in WeakMap describes how the JavaScript garbage collector treats the keys in the "weak map".

Weakness of weakcMap
"weak" in WeakMap indicates that the weakly mapped key is "weakly held." This means that these keys are not a formal reference and will not prevent garbage collection, which may be reclaimed when the browser needs to reclaim memory. However, it should be noted that the reference of values in weak mappings is not "held weakly". As long as the key exists, the key/value pair exists in the mapping and is treated as a reference to the value, so it is not treated as garbage collection.


// Will be recycled 
const wm = new WeakMap();
wm.set({}, "val");

// Will not be recycled 
const wm2 = new WeakMap();
const container = {
 key: {}
};
wm2.set(container.key, "val");
function removeReference() {
 container.key = null;
}

In vm, the set () method initializes a new object and uses it as a key to a string. Because there are no other references to this object, the object key is treated as garbage collection when this line of code is executed. Then, the key/value pair disappears from the weak mapping, making it an empty mapping. In this example, because the value is also not referenced, the value itself becomes the target of garbage collection after the key/value pair is broken.
In vm1, the container object maintains a reference to a weakly mapped key, so this object key will not be the target of garbage collection. However, if removeReference () is called, the last reference to the key object is destroyed, and the garbage collector can clean up the key/value pair.

weakMap uses
The initialization of WeakMap is not much different from that of map. It should be noted that weakMap can only use object type keys, which is closely related to the role of weakMap


const key1 = {id: 1},
 key2 = {id: 2},
 key3 = {id: 3};
//  Initializing Weak Mappings with Nested Arrays 
const wm1 = new WeakMap([
 [key1, "val1"],
 [key2, "val2"],
 [key3, "val3"]
]);
alert(wm.get(key1)); // val1
alert(wm.get(key2)); // val2
alert(wm.get(key3)); // val3

//  The original value can be wrapped as an object before being used as a key 
const stringKey = new String("key1");
const wm3 = new WeakMap([
 stringKey, "val1"
]);
alert(wm3.get(stringKey)); // "val1"

4. Scenarios using weakMap

The WeakMap instance is very different from the existing JavaScript object, and it may not be easy to say how to use it at 1. There is no one answer to this question, but many related strategies have emerged.

DOM Node Metadata
Because the WeakMap instance does not interfere with garbage collection, it is a good place to save associated metadata. As shown in the following code, the following example uses WeakMap, and when a node is removed from the DOM tree, the garbage collector releases its memory immediately (assuming there is no other reference to the object):


const wm = new WeakMap();
const loginButton = document.querySelector('#login');
//  Associate this node 1 Some metadata 
wm.set(loginButton, {disabled: true});

Summarize

These are the related uses and differences of object, map and weakmap. In fact, in most cases, there is no difference between object and map, but if you need a lot of inserts and deletions, or need to use objects as key values, using map is a better choice. In addition, weakMap has the advantage of optimizing memory over map when the objects used may be dynamically deleted.

The above is the detailed content of the difference analysis of Object, map and weakmap in JavaScript. Please pay attention to other related articles on this site for more information about the difference between Object, map and weakmap in JavaScript!


Related articles: