Set

Set 对象是 ES6 新增,特点:元素不重复。

# 不可重复

    let set = new Set([1,1,2]); // 不可重复
    console.log(set) ;

# 区分类型

    let set = new Set([1,'1',2]); // 不可重复
    console.log(set) 

# 构造函数传字符串

      let set = new Set("abc");// 等于 new Set([..."abc"])
      console.log(set)


所以 , 我们传字符串 ,需要(下面)

      let set = new Set(["abc","bbb"]);
      console.log(set)
      

# API

转载: https://blog.csdn.net/wuyujin1997/article/details/88741351

  • size 集合大小
  • add(value) - Set 添加元素。(可链式编程)
  • has(value) - boolean 查询元素是否存在。
  • delete(value) - boolean 删除
  • clear() - 清空
  • forEach(callback) - 对容器内每个元素做操作。(下面)
  • keys() - 用法同values(),因为set只有value列表。
  • values()
  • entries() - 不推荐。会返回两倍的set(见代码)。

# 类型转换

## 转换成数组

    let set = new Set(['aaa','bbb']);
    console.log(Array.from(set));
    console.log([...set])

## 转换成数组 - 应用1

    // 取 n 中小于5 的数(不重复)
    let n = '12342345242323';
    let hd = new Set(n) ; 
    let set = new Set([...hd].filter(item => item<5)) ;
    console.log(set)

## 转换成数组 - 应用2

去重

    let array = [1,1] ;
    array = [... new Set(array)] ;
    console.log(array)

# 遍历

## values、keys、entries

就那样

## forEach

    let set = new Set(['aa' , 'bb']) ;
   set.forEach((value, key, set) => {
     console.log(value, key, set) ;
   })

## for of

    let set = new Set(['aa' , 'bb']) ;
    for(const value of set ) {
      console.log(value) ;
    }

# 案例

<!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>

  <input type="text" name="hd">
  <ul></ul>

<body>
  <script> let obj = { data: new Set() , set keyword(word) { this.data.add(word) ; }, show() { let ul = document.querySelector('ul'); ul.innerHTML='' ; this.data.forEach(value => { ul.innerHTML+=`<li>${value}</li>`; }) } } let input = document.querySelector(`[name='hd']`) ; input.addEventListener('blur', function() { obj.keyword = this.value ; obj.show() ; }) </script>
</body>
</html>

# 并集、差集、交集 - 处理

    let a = new Set([1,2]) ; 
    let b = new Set([2,5]) ;
    console.log(new Set([...a, ...b])) // 并集
    console.log(// 差集合 A中不包含B
      new Set(
        [...a].filter((value) => {
          return !b.has(value);
        })
      )
    )
    console.log(// 交集
        new Set(
          [...a].filter(value => b.has(value))
        )
    )

WeakSet

# 只能添加引用类型

    let arr = ['aa', 'bb'] ;
    // let set = new WeakSet(arr) ; 会报错
    let set = new WeakSet() ;
    // set.add(arr[0]); 会报错
    set.add(arr) ;
    console.log(set) ;

# 基本用法

api 基本用法和 set 一样,只有如下 api:

  • add
  • delete
  • has

(为什么,只有这么点 api? 下面说)

<mark>主要,WeakSet 只能保存引用类型!</mark>

  let nodes = new WeakSet() ;
  let divs = document.querySelectorAll('div');
  divs.forEach(item => {
    nodes.add(item) ;
  })
  console.log(nodes)
  nodes.delete(divs[0]) ;  // 删除
  console.log(nodes)
  console.log(nodes.has(divs[1])) // 判断有误

# 特点:弱引用

Set 他不香吗,为什么要用 WeakSet?

## 引入 “垃圾回收” 概念

当没有引用,数据会被视为垃圾,被回收

  let hd = {name:'后盾人'}; // 引用 +1
  let edu = hd ; // 引用 +1
  hd = null ;// 引用 -1 
  edu = null ; // 引用 -1 
  // {name:'后盾人'} ==> 被(垃圾)回收

## 弱引用

引用数据,数据的引用数不加1,即为弱引用

  1. 使用弱引用

      let hd = {name:'后盾人'}; // 引用 +1
      let edu = hd ; // 引用 +1
    
      let set = new WeakSet() ; 
      set.add(hd) ; // 引用 +0
      console.log(set)
    

  2. 清除强引用

      let hd = {name:'后盾人'}; // 引用 +1
      let edu = hd ; // 引用 +1
    
      let set = new WeakSet() ; 
      set.add(hd) ; // 引用 +0
      console.log(set)
      edu = null ; // 引用 -1
      hd = null ; // 引用 -1 
    

可以看到,强引用清除后,弱引用的数据不会保留

这导致 无法循环、遍历(下图)

  let set = new WeakSet() ; 
  set.keys();

  let set = new WeakSet() ; 
  for (const i of set) {}


甚至无法使用 size 属性 ( 下图 )

  let set = new WeakSet() ; 
  console.log(  set.size  ) ; 

# 案例

看了 弱引用,第一眼的感觉是 “鸡肋”

那么,它存在的必要性是什么?

这篇知乎文章说了:《WeakSet 用法解惑》 - https://zhuanlan.zhihu.com/p/54889129
引用的原始文章:《ECMAScript 6: what is WeakSet for? 》 - https://stackoverflow.com/questions/30556078/ecmascript-6-what-is-weakset-for

<mark>弱引用作用:一个集合,既要判断集合元素,又不想管理集合元素的声明周期,弱引用就是必要的。</mark>

下面的案例:
有两个独立的功能:

  1. 删除集合元素(生命管理)
  2. 判断集合元素,作出对应决策

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style> ul>li{ width: 300px; background: green; } ul li a { width: 60px; display: inline-block; text-align: center; background: yellow; } .remove{ background: red; } </style>
</head>
  <ul>
    <li>https://houdunren.com <a href="javascript:;">删除</a></li>
    <li>hdcms.com <a href="javascript:;">删除</a></li>
    <li>houdunwang.com <a href="javascript:;">删除</a></li>
  </ul>
<body>
<script> class Todo { constructor() { this.items = document.querySelectorAll("ul>li") this.lists = new WeakSet() ; this.items.forEach(item => { this.lists.add(item) ; }) } run() { this.addEvent() ; } addEvent() { this.items.forEach(item => { let a = item.querySelector('a') ; a.addEventListener('click', event => { // 给a的父级加样式 const parentElement = event.target.parentElement ; if(this.lists.has(parentElement)) { parentElement.classList.add('remove') ; this.lists.delete(parentElement) ; } else { if(confirm('已删除,想要恢复?')) { parentElement.classList.remove('remove'); this.lists.add(parentElement) } } }) }) } } new Todo().run() ; </script>
</body>
</html>

get?