Introduction to the

WeakMap has a similar structure to Map and is used to generate a set of key-value pairs. JavaScript objects are essentially collections of key-value pairs, but only strings can be used as keys. ES6 provides Map data structures, which are similar to objects and are collections of key-value pairs, but the scope of “keys” is not limited to strings. Values of all types (including objects) can be used as keys. In other words, the Object structure provides string-value mapping, and the Map structure provides value-value mapping, which is a more complete Hash structure implementation.

WeakMap only accepts objects as key names and does not accept other types of values as key names, including NULL.

const map = new WeakMap(a); map.set(1.2)
// TypeError: 1 is not an object!
map.set(Symbol(), 2)
// TypeError: Invalid value used as weak map key
map.set(null.2)
// TypeError: Invalid value used as weak map key
Copy the code

The object to which the key name of WeakMap points is a weak reference and is not included in the garbage collection mechanism. As long as all other references to the referenced object are cleared, the garbage collection mechanism frees the memory occupied by the modified object.

WeakMap weakly references only the key name, not the key value. Key values are still normal references.

const wm = new WeakMap(a);let key = {};
let obj = {foo: 1};

wm.set(key, obj);
obj = null;
wm.get(key)
// Object {foo: 1}
Copy the code

We can write a small Demo of Node to verify this point:

Running Node — expose-GC on the command line allows manual garbage collection. Perform a manual garbage collection to ensure that the memoryUsage status obtained is accurate global.gc(), and then run process.memoryusage () to check the running status:

{
  rss: 21884928,
  heapTotal: 4468736,
  heapUsed: 2797232,
  external: 1685266,
  arrayBuffers: 34509
}
Copy the code

Then create a new WeakMap instance and save a large variable, let WM = new WeakMap(); let key = newArray(5*1024*1024) wm.set(key, 1)

Then manually clear the memory and check the memory again, it can be seen that the WeakMap reference to the value does not disappear:

{
  rss: 54235136,
  heapTotal: 46682112,
  heapUsed: 45074784,
  external: 1685299,
  arrayBuffers: 75462
}
Copy the code

When the reference of key is cleared, it can be seen that the object to which the key name of WeakMap points is a weak reference, which is not included in the garbage collection mechanism. As long as all other references to the referenced object are cleared, the garbage collection mechanism frees the memory occupied by the modified object.

key = null; global.gc(); process.memoryUsage(); {RSS: 12255232, heapTotal: 4734976, heapUsed: 3004776, external: 1685290, arrayBuffers: 108221}Copy the code

WeakMap differs from Map in API mainly in two aspects. First, there is no traversal operation (that is, no keys(), values() and entries() methods) and no size attribute. Second, it cannot be cleared, that is, the clear method is not supported. Therefore, WeakMap has only four methods available: get(), set(), has(), delete().

const wm = new WeakMap(a);// the size, forEach, and clear methods do not exist
wm.size // undefined
wm.forEach // undefined
wm.clear // undefined
Copy the code
usage
1. Store DOM nodes
let myWeakmap = new WeakMap(a); myWeakmap.set(document.getElementById('logo'),
  {timesClicked: 0});document.getElementById('logo').addEventListener('click'.function() {
  let logoData = myWeakmap.get(document.getElementById('logo'));
  logoData.timesClicked++;
}, false);
Copy the code

Document.getelementbyid (‘logo’) is a DOM node whose state is updated every time a click event occurs. We place this state in WeakMap as a key value, and the corresponding key name is the node object. Once the DOM node is removed, the state disappears automatically, with no risk of memory leaks.

2. Save private variables
const _private = new WeakMap(a);class Example {
  constructor() {
    _private.set(this.'private');
  }
  getName() {
  	return _private.get(this); }}var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined
Copy the code
3. Data caching
const cache = new WeakMap(a);function countOwnKeys(obj) {
    if (cache.has(obj)) {
        console.log('Cached');
        return cache.get(obj);
    } else {
        console.log('Computed');
        const count = Object.keys(obj).length;
        cache.set(obj, count);
        returncount; }}Copy the code