Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值
Map 和 Object 的区别
|
Map |
Object |
意外的键 |
Map 默认情况不包含任何键。只包含显式插入的键 |
一个 Object 有一个原型, 原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。 |
键的类型 |
一个 Map 的键可以是任意值,包括函数、对象或任意基本类型。 |
一个 Object 的键必须是一个 String 或是 Symbol |
键的顺序 |
Map 中的 key 是有序的。因此,当迭代的时候,一个 Map 对象以插入的顺序返回键值。 |
一个 Object 的键是无序的 注意:自 ECMAScript 2015 规范以来,对象确实保留了字符串和 Symbol 键的创建顺序; 因此,在只有字符串键的对象上进行迭代将按插入顺序产生键。 |
Size |
Map 的键值对个数可以轻易地通过 size 属性获取 |
Object 的键值对个数只能手动计算 |
迭代 |
Map 是 iterable 的,所以可以直接被迭代 |
迭代一个 Object 需要以某种方式获取它的键然后才能迭代。 |
性能 |
在频繁增删键值对的场景下表现更好。 |
在频繁添加和删除键值对的场景下未作出优化。 |
Map 类型特点和创建方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| let obj = { 1: "李四", "1": "张三", }; console.log(obj);
let map = new Map();
map.set("name", "李四");
map.set(1, "数字");
map.set(function() {}, "方法作为键名");
map.set({}, "对象键名"); console.log(map);
|
Map 类型的增删改查
map.set
增加
map.delete(key)
删除单个
map.clear()
删除全部
map.get(key)
查询单个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let map = new Map();
map.set("name", "李四"); map.set("age", "10");
console.log(map.delete("age"));
console.log(map.get("name"));
console.log(map);
|
遍历 Map 类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| let map = new Map(); map.set("name", "李四"); map.set("age", "15");
console.log(map.keys());
console.log(map.values());
console.log(map.entries());
for (let key of map.keys()) { console.log(key); }
for (let val of map.values()) { console.log(val); }
for (let [key, val] of map.entries()) { console.log(key, val); }
map.forEach((item, key) => { console.log(item, key); });
|
Map 类型转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| let map = new Map(); map.set("name", "李四"); map.set("age", "18");
console.log([...map]);
let newmap = [...map];
let newarr = newmap.filter((item) => { return item[1].includes("李四"); });
let map2 = new Map(newarr);
console.log(...map2.keys());
|
Map 类型操作 DOM 节点
1 2
| <div name="非常棒">songzhengxiang</div> <div name="这都被你发现了">千万别点我</div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| let map = new Map();
let divs = document.querySelectorAll("div");
divs.forEach((item) => { map.set(item, { name: item.getAttribute("name"), }); });
map.forEach((content, divitem) => { divitem.addEventListener("click", () => { alert(content.name); }); }); console.log(map);
|
Map 控制表单提交
1 2 3 4 5 6 7 8
| <form action="" onsubmit="return post()"> 服务协议 <input type="checkbox" error="请勾选协议" /> 权限管理 <input type="checkbox" error="请勾选权限管理" />
<input type="submit" value="提交" /> </form>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function post() { let error = document.querySelectorAll("[error]"); let map = new Map(); error.forEach((item) => { map.set(item, { error: item.getAttribute("error"), state: item.checked, }); }); let newmap = [...map]; return newmap.every( ([div, checkbox]) => checkbox.state || alert(checkbox.error) ); }
|
WeakMap 的使用
WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的
1 2 3 4 5 6 7
| let weakmap = new WeakMap(); const o1 = {}; const o2 = function() {}; weakmap.set(o1, "37"); weakmap.set(o2, undefined);
console.log(weakmap);
|
WeakMap 弱引用类型体验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let obj = { name: "lisi", }; let weakmap = new WeakMap(); weakmap.set(obj, "lisi");
console.log(weakmap); obj = null;
console.log(weakmap);
setTimeout(() => { console.log(weakmap); }, 1000);
|
使用 Map 开发选课组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| .kecheng { width: 300px; float: left; }
.xuanran { width: 300px; float: left; margin-top: 11px; }
ul { list-style: none; }
ul > li { border: 2px solid red; margin: 2px; width: 200px; padding: 5px; position: relative; }
li > a { text-decoration: none; position: absolute; right: 15px; background-color: green; color: white; width: 21px; text-align: center; border-radius: 3px; } .plck { padding-left: -5px; padding-top: 20px; } .plck > span { background-color: green; color: white; padding: 3px; border-radius: 2px; margin: 5px; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <div class="main"> <div class="kecheng"> <ul> <li><span>css</span> <a href="javascript:;">+</a></li> <li><span>html</span> <a href="javascript:;">+</a></li> <li><span>js</span> <a href="javascript:;">+</a></li> <li><span>vue</span> <a href="javascript:;">+</a></li> <li><span>小程序</span> <a href="javascript:;">+</a></li> </ul> </div> <div class="xuanran"> <div class="info">当前一共选择了0门课程</div> <div class="plck"></div> </div> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| class todo { constructor() { this.map = new Map(); this.lis = document.querySelectorAll("li"); this.info = document.querySelector(".info"); this.plck = document.querySelector(".plck"); } run() { this.lis.forEach((item) => { item.querySelector("a").addEventListener("click", (event) => { if (!item.getAttribute("select")) { item.setAttribute("select", true); this.map.set(item, { name: item.querySelector("span").innerHTML, }); event.target.style.backgroundColor = "red"; event.target.innerHTML = "-"; event.target.style.transition = "0.5s"; } else { item.removeAttribute("select"); this.map.delete(item); event.target.style.backgroundColor = "green"; event.target.innerHTML = "+"; event.target.style.transition = "0.5s"; } let infohtml = document.querySelector(".info"); infohtml.innerHTML = `当前一共选择了${this.map.size}门课程`; let plck = document.querySelector(".plck"); plck.innerHTML = ""; this.map.forEach((name, lis) => { plck.innerHTML += `<span>${name.name}</span>`; }); }); }); } } new todo().run();
|