js-- ES6 新增 Set 和 Map ( WeakSet 和 WeakMap) 相关知识点总结

前言

  前端开发语言 JavaScript 不像一些后端语言,集合数据类型只有数组类型,尽管数组也是通过键值对存储在内存中,且数组经常被当作队列和栈数据解构来使用,但是当遇到特殊情况的时候,比如要求键的索引是非数值类型的时候呢,用数组处理就变得十分麻烦,为了弥补这些缺点,ES6 引入了 Set 和 Map 这两种集合类型。本文就来总结一下这两种类型的具体使用方法。

正文

  1.Set类型

  Set 一种无重复值的有序列表 允许对它包含的数据进行快速访问,从而增加了一个追踪离散值的更有效的方式。Set 就像高中数学数中的集合一样,具有了确定性,唯一性,不可重复性。这里的 Set 是一个特殊的有序列表。下面是 Set 的使用方法:

  (1)初始化和创建,通过构造函数。

        // 创建set方法
        let myset = new Set()
        console.log(myset);

        // 也可以使用数组来初始化一个集合set
        let iset = new Set([0.0, 1, 2, 3, 0, 2, 3])
        console.log(iset);//把相等值合并    

  上面的代码通过构造函数来创建Set集合,同时也可以通过一个数组来初始化一个 Set 集合,由于集合中元素的唯一性,所以 iset 中元素去除了重复的数据。

  (2)添加元素,通过 add()方法

        // 创建set
        let myset = new Set()
        // 添加元素
        myset.add("5")
        myset.add(5)
        console.log(myset);//{5,"5"}
        console.log(myset.size);//2
        myset.add(-0)
        myset.add(+0)
        console.log(myset);//{5,"5",0}
        console.log(myset.size);//3

  上面的代码通过add()给创建的Set集合添加元素,需要注意,数值的 5 和字符串的 5 会被当作不同的元素保存,而数值的 +0 和 -0 会被当作0保存。

  (3)移除元素,通过  delete() 部分移除和 clear()全部移除。

        let removeSet = new Set()
        removeSet.add(1)
        removeSet.add(2)
        removeSet.add(3)
        removeSet.delete(1)
        console.log(removeSet);//{2,3}
        removeSet.clear()
        console.log(removeSet);//{}

  上面的代码通过 delete() 方法移除Set中的部分项,通过 clear() 移除集合的全部元素。

  (4)判断元素是否存在,通过has()判断。

        var hasset = new Set()
        hasset.add(1)
        console.log(hasset.has(1));//true
        hasset.delete(1)
        console.log(hasset.has(1));//false

  上面的代码添加元素1后,通过has判断集合是否存在入参元素,若存在则返回 true,否则返回 false。

  (5)Set元素遍历

        var set = new Set()
        set.add(1)
        set.add(2)
        set.add(3)
        set.forEach((v,k,set)=>{
            console.log(`v:${v}==K:${k}`);
            console.log("set",set);
        })

  上面的代码需要注意,Set 通过 forEach 遍历时候,传入的函数接收三个参数,其中分别代表:Set中当前的位置的值,与第一个参数相同的值,目标 set 自身。

  (6)使用Set实现数组去重

        var arrSet = new Set([0,1,2,0,1,2,1,1,]),
        arr = [...arrSet];
        console.log(arr);//[0,1,2]

  上面的代码再初始化 set 的时候传入一个数组,arrSet 这个集合有元素的唯一性,把重复的项合并,然后通过剩余运算符赋值给数组,最终实现了数组的去重。

  2.WeakSet类型

   由于set 类型存储对象引用的方式,对象存储在 Set 的一个实例中时,实际上相当于把对象存储再变量中。只要对于 Set  实例的引用仍然存在,所存储的对象就无法被垃圾回收机制回收,从而无法释放内存。如下面的代码:

        var myset = new Set()
        var key = {};
        myset.add(key);
        console.log(myset.size); // 1
        console.log(myset);//[{}]
        // 取消原始引用
        key = null;
        console.log(myset.size); // 1
        // 重新获得原始引用
        key = [...myset][0];
        console.log(key);//{}

  上面的代码,首先创建一个Set 集合,然后添加一个空对象,但是key变量置空后取消了对空对象的引用,Set 集合的第一项仍然保持对空对象的引用,这就阻止了 js 引擎对空对象的回收。在实际开发中,遇到 Set 内部对 key 变量值的引用要随key的引用消失而消失怎么办呢?这就产生了 WeakSet 这一集合类型,该类型值允许存储对象的弱引用,而不能储存基本类型的值,对象的弱引用在它自己成为对象的唯一引用时,不回阻止垃圾回收。

  需要知道 WeakSet也具有了Set同样的方法,除此之外做出了一定扩展而已。

        var set = new WeakSet(),
            key = {};
        // 将对象加入 set
        set.add(key);
        console.log(set.has(key)); // true
        key = null
        console.log(set.has(key)); // false

  3.Map类型

  map 类型是键值对的有序列表,而键和值可以是任意类型,键的比较可以使用 Object.is() ,因此数字型的 5 和字符串类型的 “5” 可以当作不同的键名。

  (1)初始化和创建,通过构造函数。

        //构造函数
        var map = new Map()
        console.log(map);
        //也可以使用数组来初始化一个map
        var mapData = new Map([["name", "Nicholas"], ["age", '25']]);
        console.log(mapData);

  上面的代码通过构造函数来创建 map ,同时也可以通过一个数组来初始化一个 map。打印结果如下:

  (2)添加元素,通过 set()方法

        var map = new Map()
        map.set("name", "xiaoming")//set方法传入键值对
        let key = { age: "18" }
        map.set(key, "ageValue")//对象作为键名
        console.log(map);

  map中存放键值对类型的数据,区别于普通的键值对对象,它的键可以是任意类型,包括对象作为键名。打印如下:

  (3)通过键来查询对应的值,通过 get()方法。

        var map = new Map()
        map.set("name", "xiaoming")
        let key = { age: "18" }
        map.set(key, "ageValue")
        console.log(map.get('name'));//xiaoming
        console.log(map.get(key));//ageValue

  map通过get()方法来获取指定键对应的值,入参为指定的键名,键名可以是任意类型。

  (4)判断指定键是否在map中,通过 has()来 判断,入参为指定键名,存在返回 true,否则返回 false ;

      删除指定键名以及对应的值,通过 delete()方法实现,入参为指定键名,返回是否删除成功;

      移除map中所有键和值,使得map置空,通过 clear()方法来实现,无返回值;

      size属性指明map 中包含的键值对个数。

        var map = new Map()
        map.set("name", "xiaoming")
        let key = { age: "18" }
        map.set(key, "ageValue")
        console.log(map.size);//2
        console.log(map.has("name"));//true
        console.log(map.delete("name"));//true
        console.log(map.size);//1
        console.log(map.clear());//undefined
        console.log(map.size);//0

  (5)map遍历

        let mapData = new Map([["name", "Nicholas"], ["age", '25']]);
        mapData.forEach((value,key,ownerMap)=>{
            console.log(value,"===",key);
            console.log(ownerMap);
        })

  map 的通过 forEach 遍历的时候,传入函数接收三个参数,其中分别代表:map 中当前的位置的值,与第一个参数相同的值,目标 map 自身。打印结果如下:

  4.WeakMap类型

  WeakMap 是存储对象弱引用的方式,在 WeakMap 中,所有的键必须是对象,而且这些对象都是弱引用。

     var wmap = new WeakMap()
    // wmap.set(1,2)//报错:TypeError: Invalid value used as weak map key
    var key = new Array(5)
    wmap.set(key, "aaa");
    console.log(wmap);//WeakMap{Array(5)=>"aaa"}
    wmap.delete(key);
    console.log(wmap);//WeakMap{}

写在最后

  以上就是本文的全部内容,希望给读者带来些许的帮助和进步,方便的话点个关注,小白的成长之路会持续更新一些工作中常见的问题和技术点。

posted @ 2021-07-24 16:04  zaisy'Blog  阅读(219)  评论(0编辑  收藏  举报