new Set/Map和new WeakSet/WeakMap以及WeakRef的是什么?如何使用?

new Set

1. 什么是Set()

new set()是 es6 新增的数据结构,类似于数组,但它的一大特性就是所有元素都是唯一的,没有重复的值,我们一般称为集合,Set本身是一个构造函数,用来生成 Set 数据结构。

应用场景:

  • 用于数组去重、用于字符串去重

  • 判断元素是否存在

  • 集合运算(交集、并集、差集)

注意:类似于数组,但是它是个对象类型

2. 增删改查方法

2.1 添加元素-----add()

添加某个值,返回 Set 结构本身,当添加实例中已经存在的元素,set不会进行处理添加

let list = new Set([5,6,6]);
list.add(1); 
list.add(2).add(3).add(3);  // 3只被添加了一次
console.log(list) // {5, 6, 1, 2, 3}

2.2 删除元素-----delete()

删除某个值,返回一个布尔值,表示删除是否成功

let list=new Set([1,20,30,40])
list.delete(30)   // true   //删除值为30的元素,有返回true,没有返回false
console.log(list)    // {1, 20, 40}

2.3 判断某元素是否存在-------has()

返回一个布尔值,判断该值是否为Set的成员

let list=new Set([1,2,3,4])
list.has(2)   // 有返回true,没有返回false

2.4 清除所有元素------clear()

清除所有成员,没有返回值

let list=new Set([1,2,3,4])
list.clear()
console.log(list)    // {}

3. 遍历方法

3.1 遍历 keys()

返回键名的遍历器,相等于返回键值遍历器values()

let list2=new Set(['a','b','c'])
for(let key of list2.keys()){
   console.log(key)//a,b,c
}

3.2 遍历 values()

返回键值的遍历器

let list=new Set(['a','b','c'])
for(let value of list.values()){
 console.log(value)//a,b,c
}

3.3 遍历 entries()

返回键值队的遍历器

let list=new Set(['4','5','hello'])
for (let item of list.entries()) {
  console.log(item);
}
// ['4','4']   ['5','5']   ['hello','hello'] 

3.4 遍历 forEach()

使用回调函数遍历每个成员

let list=new Set(['4','5','hello'])
list.forEach((value, key) => console.log(key + ' : ' + value))
// 4:4    5:5   hello:hello

4. 使用情形

4.1 用于数组去重

let arr = [3, 5, 2, 2, 5, 5];
let setArr = new Set(arr)     // 返回set数据结构  Set(3) {3, 5, 2}
​
//方法一   es6的...解构
let unique1 =  [...setArr ];      //去重转数组后  [3,5,2]
​
//方法二  Array.from()解析类数组为数组
let unique2 = Array.from(setArr )   //去重转数组后  [3,5,2]

4.2 用于字符串去重

let str = "352255";
let unique = [...new Set(str)].join("");     // 352 

4.3 实现并集、交集、和差集

let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
​
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
​
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
​
// (a 相对于 b 的)差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}

弊端

问题:当 set中的值被 null 掉了后,它还会一直在里面,但是操作不了

let obj = {
    name: 'aa'
}
let s1 = new Set()
s1.add(obj).add('aaa')
// 值
0: {name: 'aa'}
1: "aaa"
console.log(set.has(obj)); // true
​
​
//-----------------------------------------------------------------------
// 但是如果 obj = null 就查找不到了但是值是有的
obj = null 
console.log(set.has(obj)); // false
 for(let i of s1) {
   console.log(i);
}
// 值
{name: 'aa'}
"aaa"
// 这个时候,这个值就操作不了了
解决办法:weakset

  let obj = {
        name: 'aa'
    }
    let s1 = new WeakSet()
  s1.add(obj)
  obj = null
  console.log(s1); // 这个时候里面是空的

new WeakSet

弱集(强引用)是垃圾收集值的集合,包括对象和未注册的符号。

注意:

  • weakSet只能添加复杂类型

  • 不存在引用计数+1

  • size,for不能用了,因为里面的数不确定

1. 添加值

let wset = new WeakSet();
    let obj = {
         name: "小明"
     }
 wset.add(obj)

2. 查询值

console.log(wset.has(object)); // flase
console.log(wset.has(obj)); // true

3. 移除值

wset.delete(obj)
console.log(wset.has(obj)); // false

new Map

Map类型是键值对的有序列表,而键和值都可以是任意类型

Map 对象是键值对的集合。Map 中的一个键只能出现一次;它在 Map 的集合中是独一无二的。

应用场景:

  • 数据库操作

    • Map可以用来存储查询结果。例如我们可以将查询结果的每一行数据存储在一个Map中,其中键为列名,值为该列对应的值。这样我们就可以方便地获取每一行数据的任意一列的值。

  • 缓存

  • 计算值

1. Map与Set的区别

  • Set是一种叫做集合的数据结构,Map是一种叫做字典的数据结构

集合-----是由一堆无序的、相关联的,且不重复的内存结构【数学中称为元素】组成的组合 字典-----是一些元素的集合。每个元素有一个称作key 的域,不同元素的key 各不相同

  • Set集合是以[值,值]的形式存储元素, Map字典是以[键,值]的形式存储

2 添加键

使用 set() 来添加

const map = new Map();
let obj = {
    name: "小明"
}
map.set(obj,"111") // 第一个是键 第二个是值
​
// 可采用链式写法
map.set('flag', true).set('a',6);

3. 读取值

使用 get() 来添加,获取不到返回 undefined

map.get('flag') // true

4. 成员的数量

size 是可访问属性,返回 Map对象的成员数量。

console.log(map.size); // 3

5. 移除对象中的所有元素

clear() 方法会移除 Map 对象中的所有元素。

map.clear()
console.log(map.size); // 0

6. 查询对象中是否包含指定元素

has() 方法返回一个布尔值,指示具有指定键的元素是否存在,如果没有返回 false

console.log(map.has('a')); // true
console.log(map.has('b')); // false

7. 移除对象中的指定元素

delete() 方法用于移除 Map 对象中指定的元素。

map.delete('a')
console.log(map.has('a')); // false

8. 遍历

3.1 遍历 keys()

返回键名的遍历器,相等于返回键值遍历器values()

for(let key of map.keys()){
   console.log(key)
}
// {name: "小明"} flag a

3.2 遍历 values()

可以拿到索引的键值

console.log(map.values())
// 0 111
// 1 true 
// 2 6

返回键值的遍历器

for (let item of map.values()) {
      console.log(item);
  }
// 111 true 6

3.3 遍历 entries()

返回键值队的遍历器

for (let item of map.entries()) {
        console.log(item);
    }
// [{name: "小明"},'111']   ['flag',true]   ['a', 6] 

3.4 遍历 forEach()

forEach() 方法按照插入顺序依次对 Map 中每个键/值对执行一次给定的函数。

map.forEach(element => {
         console.log(element);
   });
// 111 true 6

弊端

// 如果把 obj 给 nulll
obj = null
// 它会跟 set 一样没有回收掉

解决办法:weakMap

跟 WeakSet 差不多,都是解决这个问题的,不会添加回收的,有回收机制

    let obj = {
           name: "aa"
    }
    let m1 = new WeakMap()
    m1.set(obj, "111")
    obj = null

new WeakMap

WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的

1. 添加值

const wmap = new WeakMap();
const obj = {
     name: "小明"
};
​
wmap.set(obj, '6');

2. 读取值

wmap.has(obj); // true

3. 获取指定键的值

wmap.get(obj) // 6

4. 移除值

wmap.delete(obj)
console.log(wmap.has(obj)); // false

案例:

当按钮失效了,点击数也要清空

<button id="like">like</button>
<script>
        let wmap = new WeakMap()
        let like = document.getElementById('like')
​
        wmap.set(like,{click: 0})
        like.onclick = function(){
            let times = wmap.get(like)
            times.click++
        }
​
        setTimeout(function(){
            document.body.removeChild(like)
            // like 需要把变量为空,要不他 dom 节点没了,但是变量还有内容
            like = null 
        },2000)
        
    
    
    // --------------- 另一种方法
     // 不使用变量获取dom
        let wmap = new WeakMap()
        wmap.set(document.getElementById('like'),{click: 0})
        document.getElementById("like").addEventListener('click',()=>{
            let times = wmap.get(document.getElementById('like'))
​
            times.click++
        },false)
​
        setTimeout(function(){
            document.body.removeChild(document.getElementById("like"))
        },2000)
</script>

WeakRef

WeakRef 对象允许您保留对另一个对象的弱引用,而不会阻止被弱引用对象被 GC 回收

强引用是指一个对象被其他对象强烈地引用,只要有强引用存在,被引用的对象就不会被垃圾回收器回收。换句话说,只有当所有强引用都不存在时,对象才会被回收。

弱引用是一种比较弱的引用关系,当一个对象只被弱引用引用时,垃圾回收器可能会在下一次运行时将其回收。弱引用通常用于缓存、观察者模式等场景,可以避免内存泄漏问题。

优化案例,使用 WeakRef

  <button id="like">like</button>
    <script>
            let wmap = new WeakMap()
            // 拿不到值直接就是 underline,wmap 直接就会被回收机制给清空了
            let like = new WeakRef(document.getElementById('like'))
        
            // 使用 deref() 来拿到值
            wmap.set(like.deref(),{click: 0})
            
            like.deref().onclick = function(){
                let times = wmap.get(like.deref())
                times.click++
            }
​
            setTimeout(function(){
                document.body.removeChild(like.deref())
            },2000)
            
    </script>

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

joshua king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值