1 Set set
Set: a data structure similar to an array without duplicate values. It is mainly used for array de duplication and string de duplication.
1.1 operation method
method | meaning |
---|---|
add() | Add a value and return the Set structure itself |
delete() | Delete value, and return a boolean indicating whether the deletion is successful |
has() | Judge whether the value exists and return a boolean |
clear() | Clear all values, no return value |
Example of using add():
let s = new Set(); s.add(1); //Add a value of 1 console.log(s); //Returns the s structure itself
The result is: set (1) {1}
let s = new Set(); s.add(1).add(2).add(1); //Add three times continuously, of which 1 is added repeatedly console.log(s); //Output Set structure itself
The result is: set (2) {1, 2}
The above code adds 1 twice, but there is only one 1 in s, so there is no duplicate value in Set. According to the observation, "Set" is added in front of the results of the first two times, and sometimes {} is the result we want, so we can use the expansion operator (...) to expand the value of Set.
let s = new Set(); s.add(1).add(2).add(1); //Add number 3 times for s console.log(...s) //Expand the value of Set
The output result is: 1 2
The output result is a sequence, which can be turned into an array by adding a [].
let s = new Set(); s.add(1).add(2).add(1); //Add number 3 times for s console.log([...s]) //Output as array
The output result is: [1, 2]
Use example of delete():
let s = new Set(); s.add(1).add(2); //Two numbers were added to the Set: 1 and 2 console.log("Before deletion:", ...s); //Output 1 2 s.delete(1); //Delete 1 console.log("After deletion:", ...s); //Output 2
The output result is:
Before deletion: 1 2
After deletion: 2
The return value of delete() is to judge whether the number has been deleted successfully. Therefore, in the previous code, the return value of s.delete(1) must be true.
let s = new Set(); s.add(1).add(2); //Two numbers were added to the Set: 1 and 2 console.log(s.delete(1)); //Output the return value after deleting 1
The output result is: true
If you delete a number that does not exist in s, its return value is false.
let s = new Set(); s.add(1).add(2); //Two numbers were added to the Set: 1 and 2 console.log(s.delete(3)); //Output the return value after deleting 3 console.log(...s); //Output s
The result is:
false
1 2
It can be seen from the above results that if a nonexistent number is deleted, its return value is false, but it does not affect the original Set result. The program will not report an error and will normally output the original Set.
has() usage example:
let s = new Set(); s.add(1).add(2); //Add two numbers 1 and 2 to s console.log(s.has(1)); //Judge whether 1 is included in s console.log(s.has(3)); //Judge whether 3 is included in s
The result is: true or false
If the value exists in the Set set, the return value is true; If the value does not exist in the Set collection, the return value is false.
clear() usage example:
let s = new Set(); s.add(1).add(2); //Add two numbers 1 and 2 to s s.clear(); //Clear all values console.log(s);
The output result is: Set(0) {}
1.2 traversal method
Since Set has only key value but no key name, it can also be said that the key and value are the same (the key and value are the same and can be omitted), and the returned values of keys and values are the same.
let set = new Set(); set.add(1).add(2).add(3); //Add 3 numbers: 1, 2, 3 for (let i of set.keys()) { //Traverse the keys of the set set, and keys() represents the keys console.log(i); //Key of output set set }
The output result is: 1 2 3
let set = new Set(); set.add(1).add(2).add(3); //Add 3 numbers: 1, 2, 3 for (let i of set.values()) { //Traverse the keys of the set set, and keys() represents the keys console.log(i); //Key of output set set }
The output result is: 1 2 3
let set = new Set(); set.add("hello").add("world"); //Add two strings for (let i of set.entries()) { //Traverse the key value pair of set, and entries() represents the key value pair console.log(i); //Output traversal results }
The output result is:
[ 'hello', 'hello' ]
[ 'world', 'world' ]
Use forEach() to traverse the Set collection.
let set = new Set(); set.add("hello").add("world"); //Add two strings to set set.forEach((key, val) => { //Traversal keys and values console.log(key + "||" + val); //Output keys and values })
The output result is:
hello||hello
world||world
Set can accept an array as a parameter.
let arr = ["Xiao Hong", "Xiao Ming", "cockroach", "Xiao Ming"]; let set = new Set(arr); //Pass the arr array as a parameter to the set set console.log(...set); //Output set set
The result is: Xiao Hong, Xiao Ming, Xiao Qiang
[case] Set realizes Union and intersection.
let arr1 = [4, 5, 6]; let arr2 = [5, 6, 7]; let setA = new Set(arr1); let setB = new Set(arr2); //Merge sets, merge two sets together, and remove redundant and repeated numbers let bingji = new Set([...setA, ...setB]); console.log(...bingji); //Output union results //Find the intersection, merge the two sets together, find the repeated numbers, and use the filter filter to get the results //Filter out the values contained together with setB in setA let jiaoji = new Set([...setA].filter(val => setB.has(val))); console.log(...jiaoji); //Output intersection results
The result is:
4 5 6 7
5 6
1.3 WeakSet
A WeakSet can only be a collection of objects, not any value of any type.
References to objects in the WeakSet collection are weak references. If there are no other references to objects in the WeakSet, these objects will be garbage collected.
This also means that there is no list of current objects stored in the WeakSet. Because of this, the WeakSet cannot be enumerated. That is, the reference to the object in the WeakSet will not be considered into the garbage collection mechanism, that is, as long as no other object references the object, the object will be recycled, regardless of whether it is in the WeakSet or not.
WeakSet supports add, has and delete methods, but does not support size and keys(), and is not iterative and cannot be traversed.
Add an object to the weakSet and view its return value:
let jack = { name: "jack" }; //jack is an object let weakSet = new WeakSet(); weakSet.add(jack); //Add an object for the weakSet console.log(weakSet.has(jack)); //Judge whether the weakSet contains jack and output the return value
The result is: true
Delete the object just added and view the return value:
let jack = { name: "jack" }; //jack is an object let weakSet = new WeakSet(); weakSet.add(jack); //Add an object for the weakSet weakSet.delete(jack); //Remove jack from the weakSet console.log(weakSet.has(jack)); //Judge whether the weakSet contains jack and output the return value
Result: false
Add content other than objects to the WeakSet and view its results:
let jack = { name: "jack" }; //jack is an object let weakSet = new WeakSet(); weakSet.add(1); //Add a value other than the object to the weakSet
The program will report an error: TypeError: Invalid value used in weak set, because only objects can be stored in the weak set.
Application scenario / benefit of WeakSet: it is used to store DOM nodes without worrying about memory leakage when these nodes are removed from the document.
2 Map set
2.1 Map overview
JavaScript objects are essentially a collection of key value pairs (Hash structure), but traditionally they can only use strings as keys. This brings great restrictions to its use.
To solve this problem, ES6 provides a Map data structure. It is similar to an Object and is also a collection of key value pairs, but the range of "key" is not limited to strings, and various types of values (including objects) can be used as keys. In other words, the Object structure provides the correspondence of "string value" and the Map structure provides the correspondence of "value value", which is a more perfect Hash structure implementation.
The Map type in ES6 is an ordered list storing many key value pairs, in which the key name and corresponding value support all data types. The equivalence of key names is determined by calling object Is () method, so the number 5 and the string "5" will be determined as two types and can appear in the program as two independent keys, which is different from the object, because the attribute name of the object will always be cast into the string type.
be careful:
1. With one exception, the Map collection treats + 0 and - 0 as equal, which is the same as object Is () results are different.
2. If the data structure of "key value pair" is required, Map is more suitable than Object and has extremely fast search speed
2.2 basic methods and attributes
1. Attribute: size, returns the number of elements in the Map
2. Basic method
method | meaning |
---|---|
set() | Add data to the Map and return the added Map (assigning values to existing keys will overwrite the previous values) |
get() | Get the value of a key and return the value corresponding to the key. If there is no key, return undefined |
has() | Detects whether a key exists and returns a Boolean value |
delete() | Delete a key and its corresponding value, return Boolean value, success: true; Failed: false |
clear() | Clear all values and return undefined |
Usage example of size and set():
let map = new Map(); map.set("name", "Orange cat is not fat"); //Add data to map map.set("age", 2); //Add data to map console.log(map.size); //Number of elements in the output map (length) console.log(map); //Output map after adding data
The output result is:
2
Map(2) {'name' = > 'orange cat is not fat', 'age' = > 2}
Use example of get():
let map = new Map(); map.set("name", "Orange cat is not fat"); //Add data to map map.set("age", 2); //Add data to map console.log(map.get("name")); //Output the value corresponding to name console.log(map.get("address")); //undefined when there is no key
The output result is:
Orange cat is not fat
undefined
has() usage example:
let map = new Map(); map.set("name", "Orange cat is not fat"); //Add data to map map.set("age", 2); //Add data to map console.log(map.has("name")); //Determine whether the map contains name console.log(map.has("address")); //Determine whether the map contains address
The output result is:
true
false
Use example of delete():
let map = new Map(); map.set("name", "Orange cat is not fat"); //Add data to map map.set("age", 2); //Add data to map console.log(map.delete("name")); //Delete name in map console.log(map.delete("address")); //Delete address in map
The output result is:
true
false
clear() usage example:
let map = new Map(); map.set("name", "Orange cat is not fat"); //Add data to map map.set("age", 2); //Add data to map console.log(map); //Output map after adding value console.log(map.clear()); //Output the return value after clearing all values console.log(map); //Output map after clearing value
The output result is:
Map(2) {'name' = > 'orange cat is not fat', 'age' = > 2}
undefined
Map(0) {}
2.3 traversal method
Note: the traversal order of the Map is the insertion order
method | meaning |
---|---|
keys() | Get all key s of Map |
values() | Get all values of Map |
entries() | Get all Map members |
forEach() | Traverse all members of the Map |
//Create a map collection and pass in a two-dimensional array const map = new Map([ ["F", "no"], ["T", "yes"] ]) console.log(map);
The output result is: Map(2) {'F' = > 'no','T '= >' yes'}
Examples of using keys():
//Create a map collection and pass in a two-dimensional array const map = new Map([ ["F", "no"], ["T", "yes"] ]) for (let key of map.keys()) { //Key traversing map console.log(key); //Key to output map }
The output result is: F T
Examples of using values():
//Create a map collection and pass in a two-dimensional array const map = new Map([ ["F", "no"], ["T", "yes"] ]) for (let value of map.values()) { //Traversal map values console.log(value); //Output map value }
The output result is:
no
yes
Examples of using entries():
//Create a map collection and pass in a two-dimensional array const map = new Map([ ["F", "no"], ["T", "yes"] ]) for (let item of map.entries()) { //Traverse all map members console.log(item); //Output all map members }
The output result is:
[ 'F', 'no' ]
[ 'T', 'yes' ]
Or:
//Create a map collection and pass in a two-dimensional array const map = new Map([ ["F", "no"], ["T", "yes"] ]) for (let [key, value] of map.entries()) { //Traverse map members console.log(key, value); //Output map member }
The output result is:
F no
T yes
Or:
const map = new Map([ ["F", "no"], ["T", "yes"] ]) // Equivalent to using map entries() for (let [key, value] of map) { //Traverse map members console.log(key, value); //Output map member }
The output result is:
F no
T yes
2.4 convert to array
A quick way to convert a Map structure to an array structure is to use the extension operator (...).
//Create a map collection const map = new Map([ [1, "one"], [2, "two"], [3, "three"] ]) //Convert the key of the map into an array console.log(...map.keys()); //1 2 3 //Convert the value of the map into an array console.log(...map.values()); //one two three //Convert the map object into an array console.log(...map.entries()); //[ 1, 'one' ] [ 2, 'two' ] [ 3, 'three' ] //Convert map to an array console.log(...map); //[ 1, 'one' ] [ 2, 'two' ] [ 3, 'three' ]
2.5 Map traversal and filtering
Combined with the map method and filter method of array, the traversal and filtering of map can be realized.
const map0 = new Map(); map0.set(1, "a"); //Add data for map0 map0.set(2, "b"); //Add data for map0 map0.set(3, "c"); //Add data for map0 //Use of filter() const map1 = new Map( //Filter out the key less than 3 in map0 [...map0].filter(([k, v]) => k < 3) ); console.log(map1); //Map(2) { 1 => 'a', 2 => 'b' } //Use of map() const map2 = new Map( //Change the key of the member in map0 to 2 times, and add "" in front of the value [...map0].map(([k, v]) => [k * 2, "_" + v]) ) console.log(map2); //Map(3) { 2 => '_a', 4 => '_b', 6 => '_c' }
2.6 forEach()
const map = new Map([[1, 'one'], [2, 'two'], [3, 'three']]); map.forEach((value, key, map) => { console.log(value, key, map); })
The output result is:
one 1 Map(3) { 1 => 'one', 2 => 'two', 3 => 'three' }
two 2 Map(3) { 1 => 'one', 2 => 'two', 3 => 'three' }
three 3 Map(3) { 1 => 'one', 2 => 'two', 3 => 'three' }
2.7 WeakMap
WeakMap is a collection of weakly referenced maps and is also used to store weak references to objects. The key name in the WeakMap collection must be an object. If a non object key name is used, an error will be reported.
The weak references of these objects are saved in the collection. If there are no other strong references besides the weak references, the garbage collection mechanism of the engine will automatically recycle this object and remove the key value pairs in the WeakMap collection. However, only the key name of the collection complies with this rule. If the value corresponding to the key name is an object, it saves a strong reference to the object and will not trigger the garbage collection mechanism.
1. Using the WeakMap collection
The WeakMap type in ES6 is an unordered list that stores many key value pairs. The key name of the list must be an object of non null type, and the value corresponding to the key name can be of any type.
The interface of WeakMap is very similar to that of Map. Data is added through the set() method and obtained through the get() method.
let map = new WeakMap(); const o1 = {}; //o1 is an empty object const o2 = function () { }; //o2 is an empty function map.set(o1, o2); //Add data to the map. The key and value can be any object, or even another WeakMap object map.set(o2, "Orange cat is not fat"); //Add data to map console.log(map.get(o1)); //[Function: o2] console.log(map.get(o2)); //Orange cat is not fat
The size property is not supported for the WeakMap collection, so it cannot be verified that the collection is empty.
2. Methods supported by the WeakMap collection
method | meaning |
---|---|
has() | Detects whether the given key exists in the collection |
delete() | Removes the specified key value pair |
has() usage example:
let map = new WeakMap(); const o1 = {}; //o1 is an empty object const o2 = function () { }; //o2 is an empty function map.set(o1, o2); //Add data to the map. The key and value can be any object, or even another WeakMap object map.set(o2, "Orange cat is not fat"); //Add data to map console.log(map.has(o1)); //Judge whether the map contains o1 and true console.log(map.has(o3)); //Judge whether the map contains o3, and the program reports an error. ReferenceError: o3 is not defined
Use example of delete():
let map = new WeakMap(); const o1 = {}; //o1 is an empty object const o2 = function () { }; //o2 is an empty function map.set(o1, o2); //Add data to the map. The key and value can be any object, or even another WeakMap object map.set(o2, "Orange cat is not fat"); //Add data to map console.log(map.delete(o1)); //If o1 in the map is deleted, true will be returned if the deletion is successful console.log(map.has(o1)); //Determine whether the map contains o1
The output result is: true or false
3. Purpose of the WeakMap collection
- Store DOM elements
<button id="btn">click</button> <script> //Get button element let myElement = document.getElementById("btn"); let myWeakmap = new WeakMap(); //Add data for myWeakmap myWeakmap.set(myElement, { timesClicked: 0 }); //Add a click event for the button myElement.addEventListener("click", function () { //Gets the value whose myWeakmap key is myElement let logoData = myWeakmap.get(myElement); //Click once plus 1 logoData.timesClicked++; //Output hits console.log(logoData.timesClicked); }) </script>
In the code, myElement is a DOM node that updates the status whenever a click event occurs. We put this state as a key value in the WeakMap, and the corresponding key name is myElement. Once the DOM node is deleted, the state will disappear automatically, and there is no risk of memory leakage
- Register the listener object that listens to events, which is very suitable to be implemented with WeakMap.
<button class="element1">Button 1</button> <button class="element2">Button 2</button> <script> //Get element let element1 = document.querySelector(".element1"); let element2 = document.querySelector(".element2"); const listener = new WeakMap(); //Add two data for listener listener.set(element1, "handler1"); listener.set(element2, "handler2"); //Add a click event for element1 element1.addEventListener("click", function () { console.log(listener.get(element1)); }) //Add a click event for element2 element2.addEventListener("click", function () { console.log(listener.get(element2)); }) </script>
The listening function is placed in the WeakMap. Once the DOM object disappears, the listener function bound to it will also disappear automatically.
- Deploy private properties
When we create objects, we usually write a constructor.
function Person(name) { this._name = name; } Person.prototype.getName = function () { return this._name; }
However, when creating a Person object, we can directly access the name attribute:
const person = new Person("Orange cat is not fat"); console.log(person._name); //Orange cat is not fat
Instead of allowing users to directly access the name attribute, we can wrap the name as a private attribute using the following method.
let Person = (function () { let privateData = new WeakMap(); function Person(name) { //Define a function with the parameter name privateData.set(this, { name: name }); //Set data for privateData } Person.prototype.getName = function () { //Set getName function return privateData.get(this).name; //Gets the name of the value of the name key in privateData } return Person; }()); //() called after the function is set const person = new Person("Orange cat is not fat"); console.log(person.getName());