Quickly understand the Set and WeakSet of ES6

Keywords: Javascript Front-end ECMAScript Programmer

Before ECMAScript 6, arrays can be used to store values, and ECMAScript 6 adds two collection types: Set and WeakSet.

Set

Set set can use new to create an empty set:

const s = new Set();

You can also initialize an instance when creating a Set:

const s = new Set(["Xiao Zhao", "Xiao Ming", "Kasumi "]);

You can also customize the iterator when initializing the Set instance.

const s = new Set({
    [Symbol.iterator]: function*() {
        yield "Xiao Zhao";
        yield "Xiao Ming";
        yield "Kasumi ";
    }
});

You can use the size property to get the number of Set instances.

After initialization, you can use the has() method to query whether an element exists:

s.has("Xiao Zheng");    // false

You can add elements using the add() method:

s.add("Xiao Ling");

Use the delete() method to delete the element and return a boolean value to judge whether there is a value to delete:

s.delete("Xiao Ming");    // true

Clear the Set instance using the clear() method:

s.clear();

Of course, similar to Map, Set can contain any JavaScript data type as a value, and uses the SameValeZero operation to check the matching of values using strict object equality criteria.

const s = new Set();
// The SameValueZero check means that independent instances do not conflict
alert(s.has(function() {})); // false

Set provides an Iterator to generate the collection contents in the order of insertion. The Iterator can be obtained through the values() method and its alias keys() method, or through the Symbol.iterator property:

const s = new Set(["Xiao Zhao", "Xiao Ming", "Kasumi "]);
s.values === s[Symbol.iterator]    // true
s.keys === s[Symbol.iterator]    // true
for (let value of s.values()) {
    console.log(value);
}
// Xiao Zhao
// Xiao Ming
// Kasumi 
for (let value of s[Symbol.iterator]()) {
    console.log(value);
}
// The output is the same as above

You can also convert a collection to an array:

const s = new Set(["Xiao Zhao", "Xiao Ming", "Kasumi "]);
console.log([...s]); // ["Xiao Zhao", "Xiao Ming", "Xiao Xia"]

The collection also provides the entries() method, which returns the [value, value] array of the values of all elements in the insertion order. It is similar to Map, but the keys and values of each value here are equal.

You can also use the forEach() method to traverse the collection:

const s = new Set(["Xiao Zhao", "Xiao Ming", "Kasumi "]);
s.forEach((v1, v2) => console.log(`${v1} -> ${v2}`));
// Xiao Zhao - > Xiao Zhao
// Xiao Ming - > Xiao Ming
// Xiaoxia - > Xiaoxia

WeakSet

The WeakSet is also a new Set in ECMAScript 6 and a subset of the Set. However, when the value in the WeakSet is not referenced, it will be recycled by GC.

Here, use the new keyword to instantiate an empty WeakSet:

const ws = new WeakSet();

It can also be initialized at creation time, but the value of WeakSet can only be Object or a subclass inherited from Object:

const val1 = {id: 1},
val2 = {id: 2},
val3 = {id: 3};
// Initializing weak collections with arrays
const ws1 = new WeakSet([val1, val2, val3]);

If a value other than an object is used, a TypeError will be thrown:

const ws2 = new WeakSet([val1, "BADVAL", val3]);
// TypeError: Invalid value used in WeakSet
typeof ws2;

The reason why we restrict the use of Object as the value here is to ensure that the value can be obtained only through the reference of the value Object. If the original value is allowed, there is no way to distinguish the literal amount of the string used during initialization from an equal string used after initialization.

After initialization, you can also use the add() method to add elements, the has() method to query elements, and the delete() method to delete elements, just like Set.

Weak value

The difference between WeakSet and Set is that GC recycling is not prevented when the values in the Set are not referenced. As follows:

const ws = new WeakSet();
ws.add({});

add() method adds a new element, but this element has no other references, so this element will be garbage collected as an empty collection. However, when the {} element is referenced by an object, it will not be recycled as garbage, as shown below:

const ws = new WeakSet();
const q = {v:{}};
ws.add(q.v);

In the above example, q.v will not be the target of GC recycling. However, if you destroy the last reference, such as pointing q.v to null, GC can clean up and recycle this value.

Non iterative value

Like the WeakMap, the values in the WeakSet may be destroyed at any time, so it does not provide the ability to iterate. Therefore, it will not get the value from the WeakSet without knowing its object reference.

application

Here, you can use the WeakSet to store elements with the same label, which is more convenient in future queries. For example, DOM elements with disable labels are stored in the WeakSet:

const des = new WeakSet();
const lb = document.querySelector('#login');
// By adding the corresponding set, this node is labeled "disabled"
des.add(lb);

In this way, when DOM elements are deleted from the DOM tree, the elements in the WeakSet instance will also be recycled by GC to free memory.

The reason why Set is not used here is that after it is deleted in the DOM tree, the Set instance will not let the GC recycle the element.

More content, please pay attention to the official account of the sea.

Posted by mukunthan on Sun, 21 Nov 2021 18:16:25 -0800