Map and WeakMap
Characteristics and creation of Map type
To understand Map, first look at the objects. Compare the objects to learn about Map.
For an object, the key in the object can only be a string!!
let obj = { 1:'lihuina', "1":"lhn" } console.log(obj); //{1: "lhn"}
When defining an object, although the key can be defined as a number, only the following one will be printed. The number 1 above will be automatically converted into a string, and the following will overwrite the above one
let hd= { //Here, we need to enclose obj with [] so that we can get the object we defined, otherwise it is just an ordinary key name [obj]:"baby" } // To get the value in obj // According to the printed hd results, we need console.log(hd["[object Object]"]); // perhaps console.log(hd[obj.toString()]);
The printed results are shown in the figure
But Map, anything can be used as a key name
// Map creation let map = new Map(); //Whether it is a string, function, object or value, it can be used as a key name map.set("name","lihuina"); map.set(function(){},"baby"); map.set({},"jjjj"); map.set(1,"ggggg");
After printing the results, you can more clearly see that the Map exists in the form of key value pairs
Map supports chain operation
For example, chain operation of string (continuous call method):
let str = 'abc'; console.log(str.toLowerCase().substr(1,1));
Chain operation in Map (for example, you can continuously add key value pairs to Map)
let map = new Map([['name','lihuina'],['age',18]]); map.set("sina","xinlang").set("baidu","Baidu").set("blog","Blog"); console.log(map);
Add, delete, modify and query Map
let map = new Map();
Add element set()
let obj = { name:"Li Si" }; map.set(obj,'lisi'); map.set('name','lhn');
Get element ()
console.log(map.get(obj));
Determine whether has() exists
console.log(map.has(obj));
Delete element
console.log(map.delete(obj)); console.log(map);
Clear element ()
map.clear(); console.log(map);
Traverse Map
let map = new Map([['name','lihuina'],['age',18]]); map.set("address","jgsu");
Get all keys()
console.log(map.keys());
Get all values()
console.log(map.values());
Get all key value pairs entries()
console.log(map.entries());
loop
forof
// Cyclic key for (const key of map.keys()) { console.log(key); } // Cyclic value for (const value of map.values()) { console.log(value); } // Circular key value pair for (const [key,value] of map.entries()) { console.log([key,value]); }
foreach
map.forEach((key,value) => { console.log(key,value); });
Map type conversion
let map = new Map([['name','lihuina'],['age',18]]);
Map = > array
Point grammar
console.log([...map]);
You can also convert keys or values separately
console.log([...map.keys()]); console.log([...map.values()]);
give an example:
If you want to take out the value lihuina alone and turn it into a new set, the others remain unchanged
// First it becomes an array, and then the filter finds what you want let newArr = [...map].filter(item => { return item.includes('lihuina'); }); // Back to the set let edu = new Map(newArr); console.log(...edu.values()); // lihuina
Map type management DOM node
let map = new Map(); document.querySelectorAll('div').forEach(item=>{ map.set(item,{ // The key name is div, and the content is the attribute value, which can store any information related to DOM nodes content:item.getAttribute('name') }); }); console.log(map);
A prompt message will pop up when clicking
// A prompt message will pop up when clicking map.forEach((config,elem)=>{ // console.log(config); // console.log(elem); elem.addEventListener("click",()=>{ alert(config.content); }); })
Example: use map type to control form submission
When you click Submit, you will call the post method to add the contents of the checked items to the map, take the object as the key value, the key is the form DOM element, and the value is the error information and whether it is selected. The map type can facilitate us to store these two types of data.
<body> <form action="" onsubmit="return post()"> Acceptance agreement: <input type="checkbox" name="agreement" error='Please accept the agreement'> I am a student: <input type="checkbox" name="student" error='The website is only open to students'> <input type="submit"> </form> <script> function post(){ let map = new Map(); let inputs = document.querySelectorAll("[error]"); // console.log(inputs); inputs.forEach(item=>{ map.set(item,{ error:item.getAttribute('error'), status:item.checked }); }); // Convert the map into an array and use the every method. Only when all are checked and the status is all true can the submission be allowed, otherwise an error message will pop up // Return status information. If one is unchecked, it will return false, and submission is not allowed // If you pass only one parameter elem, you will get an array. The first is an element and the second is a json object, // If you want to get a json object, you have to use elem[1] to get it // Deconstruction can be used here, and the second is config, so config can directly get the data we want return [...map].every(([elem,config])=>{ // If the status is true, do nothing. If it is false, an error message will pop up config.status || alert(config.error); return config.status; }) // console.log(map); // return false; } </script> </body>
WeakMap
The key in WeakMap can only be an object. For example, the value of weakset must be an object
let map = new WeakMap(); // An error will be reported when the key is a string // map.set("name","lihuina"); // Invalid value used as weak map key at WeakMap.set (<anonymous>) // If the key is a reference type (array, object, etc.), no error will be reported map.set([],"lihuina"); //WeakMap {Array(0) => "lihuina"} console.log(map);
DOM elements are objects
<body> <!-- DOM Elements are objects --> <div>lihuina</div> <div>baby</div> <script> let divs = document.querySelectorAll('div'); let map = new WeakMap(); divs.forEach(item=>map.set(item,item.innerHTML)); console.log(map); </script> </body>
Addition, deletion, modification and query of WeakMap
// Basic grammar let arr = []; //Array is a reference type let map = new WeakMap(); // add to map.set(arr,'lihuina'); // delete map.delete(arr); // judge console.log(map.has(arr)); // Values keys size for of console.log(map);
Weak type characteristics
let hd = {name:"lihuina"}; // First, let both hd and cms variables point to this object let cms = hd; let map = new WeakMap(); // Then let the key in the map point to this object map.set(hd,"lihuina.com"); // Let neither hd nor cms point to this object hd = null; cms = null; //At this time, the garbage collection mechanism should have come // At this time, when printing the map, the existing children will still be displayed console.log(map); // Let's take a look at it with a timer // The browser versions are different. Some browsers can display it all at once with the setTimeOut timer. My browser takes a little longer to display it. Just look at the print result directly setInterval(function(){ console.log(map); },1000);
-
After clearing hd and cms, the map will still be printed. At the beginning of emptying, WeakMap did not perceive it
-
After a period of time, this problem will be found after the system self-test, and then it will be corrected
-
Because of this problem, WeakMap doesn't let us use values keys size for of these methods
-
After setting the timer, you will find that it will not be available for a period of time
-
Therefore, when using this feature to save data using WeapMap, there is no need to clean it manually. As long as the external data changes, it will disappear by itself
-
Therefore, WeakMap is mainly used to save externally affected data
Example: using WeakMap to develop course selection components
At the end of the rendering, the code explanation is put in the comments
(without css code, you can design it yourself)
You can run and debug it yourself
<body> <div class="ke"> <ul> <li><span> lihuina</span><a href="javascript:;">+</a></li> <li><span> baby</span><a href="javascript:;">+</a></li> <li><span> lihuina.com</span><a href="javascript:;">+</a></li> </ul> </div> <div class="text"> <strong id="count">A total of 0 courses were selected</strong> <p id="lists"></p> </div> <script> class Lesson{ constructor(){ this.lis = document.querySelectorAll("ul>li"); // console.log(this.lis); this.countElem = document.getElementById('count'); this.listsElem = document.getElementById('lists'); // console.log(this.countElem); // console.log(this.listsElem); this.map = new WeakMap(); } run(){ this.lis.forEach(li=>{ li.querySelector('a').addEventListener('click',event=>{ // console.log(li); // console.log(event.target.parentElement); const a = event.target; // console.log(this); const state = li.getAttribute('select'); if(state){ li.removeAttribute('select'); this.map.delete(li); a.innerHTML = "+"; a.style.backgroundColor = 'green'; }else{ this.map.set(li); li.setAttribute('select',true); a.innerHTML = "-"; a.style.backgroundColor = 'red'; } // console.log(this.map); this.render(); }); }); } lists(){ return [...this.lis].filter(li=>{ return this.map.has(li); }).map(li=>{ return `<span>${li.querySelector('span').innerHTML }</span>`; }).join(" "); } count(){ return [...this.lis].reduce((count,li)=>{ return count += (this.map.has(li)?1:0); },0); } render(){ this.countElem.innerHTML = `Co selected ${this.count()}Course`; this.listsElem.innerHTML = this.lists(); } } new Lesson().run(); </script> </body>
The article comes from the notes of watching the supporter course (made by yourself). If you have any problems, please correct them