头图

Map是一组键值对的结构,函数、对象、基本类型都可以作为键或值。

1.声明定义及基本操作

  1. set()方法相当于set中的add()方法,用于向集合中添加元素,当参数为一个值时,参数作为键名,有两个参数时,作为键值对。参数为Map中已有的键名时,则会修改对应的value值。参数为引用类型或者数字类型。
    var m1 = new Map();
    m1.set('name');
    m1.set(function f1() { }, 18);
    m1.set('sex', 'man');
    m1.set({},{})
    console.log(m1);;

image.png

  1. 接受一个数组作为参数,该数组的成员是一个表示键值对的数组。

    let m = new Map([
      ['陕西', '西安'],
      ['湖南', '长沙']
    ]);
    
    console.log(m.get('陕西')); //西安
    

2.使用set向map中添加元素支持链式操作

链式操作(也称为链式调用或链式语法)是一种常见的编程模式,它通过在对象上连续调用方法来实现复杂的操作。每个方法都返回一个可以再次被调用的对象,从而形成一种“链式”结构。
let map = new Map();
let obj = {
  name: "小明"
};

map.set(obj, "小明儿子").set("name", "小明孙子").set("age",1234);

console.log(map.entries()); 

注意看结果,虽然是链式操作,但是key-value都是相互独立的,不过是可以更方便的添加数据而已.

image.png

3.map长度
console.log(map.size);

4.判断元素是否存在,返回true或false

map.has('age');

5.读取元素

map.get('age');

请看下面的例子:

     var m1 = new Map();
    m1.set(function f1() {}, 18);
    console.log(m1);
    console.log(m1.get(function f1() {}));

image.png
在这种情况下,为什么我们打印Map可以看到function f1() {} => 18;为什么get(function f1() {})显示的却是undefined ?

这是因为每次创建一个新的函数,都会创建一个新的对象。即使两个函数的内容完全相同,它们也被视为两个不同的对象。所以,当你试图使用 m1.get(function f1() { }) 获取值时,你实际上是在创建一个新的函数对象,而这个新的函数对象并没有在你的Map m1 中。

如果你想要通过函数来获取值,你需要将函数保存到一个变量中,然后使用这个变量来设置和获取值。例如:

var m1 = new Map();
var f1 = function() { };
m1.set(f1, 18);
console.log(m1.get(f1)); // 输出:18

6.删除元素
清除单个
map.delete('age');
清除全部
map.clear();

2.遍历map

使用 keys()/values()/entries() 都可以返回可遍历的迭代对象

let map1 = new Map([["陕西", "西安"], ["河北", "石家庄"]]);
console.log(map1.keys()); //MapIterator {'陕西', '河北'}
console.log(map1.values()); //MapIterator {'西安', '石家庄'}
console.log(map1.entries()); //MapIterator {'陕西' => '西安', '河北' => '石家庄'}

换一种方式实现entries的效果.

let map1 = new Map([["陕西", "西安"], ["河北", "石家庄"]]);

for(const [key,value] of map1){
  console.log(`${key} => ${value}`);
}

3.实例(勾选所有的checkbox才可以进行提交)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <form action="" onsubmit="return post()">
      规则1:
      <input type="checkbox" name="1" mes="请选择1">
      规则2:
      <input type="checkbox" name="2" mes="请选择2">

      <input type="submit" name="" id="">
      
  </form>
</body>
</html>
<script>

function post(){
  let inputs = document.querySelectorAll('[mes]');
  let map = new Map();
  inputs.forEach(item =>{
    map.set(item, {
        mes: item.getAttribute("mes"),
        status: item.checked
      })
  });

  return [...map].every(([item,value]) => {
    value.status || alert(value.mes);
    return value.status
  })
}
</script>

代码解释

value.status || alert(value.mes);
这一行其实是利用了 '||'运算的短路特性(有一个为真,第二个就不运行了,直接跳过)

4.WeakMap介绍

在JavaScript中,Map和WeakMap都是内置的数据结构,用于存储键值对。它们之间的主要区别在于以下几点:

  1. 键类型的限制:在Map中,键可以是任意类型的值(包括基本类型和对象引用),而在WeakMap中,键只能是对象引用。

     var m1 = new WeakMap([[function f1() { }, '函数']]);
     console.log(m1);
     var m2 = new WeakMap([['name', '张三']]);
     console.log(m2);

image.png

  1. 垃圾回收机制:在Map中,如果某个键不再被引用,它仍然会被Map引用,并且不会被垃圾回收。而在WeakMap中,如果某个键不再被引用,它会被自动从WeakMap中删除,这也是WeakMap的一个特性,可以避免内存泄漏。
  2. 迭代:在Map中,可以使用 Map.prototype.keys() 、 Map.prototype.values() 和 Map.prototype.entries() 等方法来迭代Map中的键、值或键值对,而在WeakMap中,由于键是对象引用,无法直接迭代键或值。
  3. 功能:Map相比WeakMap提供了更多的功能,比如可以获取Map的大小(使用 Map.prototype.size 属性),可以通过键获取值(使用 Map.prototype.get() 方法),可以遍历Map中的键值对等。而WeakMap相对简单,只提供了 WeakMap.prototype.get() 、 WeakMap.prototype.set() 、 WeakMap.prototype.has() 和 WeakMap.prototype.delete() 等基本操作。

Map适用于一般的键值对存储需求,而WeakMap更适用于需要存储对象关联信息且不希望干扰垃圾回收的场景(也就是说数据如果除WeakMap使用,外部无人访问时可以被回收)。

WeakMap类似于WeakSet,请查看javascript 中Set与WeakSet 是什么?一文)


豪爽和龙虾
1 声望0 粉丝