欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JS - 6 - Set 和 WeakSet - 弱引用

程序员文章站 2022-05-20 14:57:02
...

Set

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

# 不可重复

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

JS - 6 - Set 和 WeakSet - 弱引用

# 区分类型

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

JS - 6 - Set 和 WeakSet - 弱引用

# 构造函数传字符串

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

JS - 6 - Set 和 WeakSet - 弱引用
所以 , 我们传字符串 ,需要(下面)

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

JS - 6 - Set 和 WeakSet - 弱引用

# 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])

JS - 6 - Set 和 WeakSet - 弱引用

## 转换成数组 - 应用1

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

JS - 6 - Set 和 WeakSet - 弱引用

## 转换成数组 - 应用2

去重

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

JS - 6 - Set 和 WeakSet - 弱引用

# 遍历

## values、keys、entries

就那样

## forEach

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

JS - 6 - Set 和 WeakSet - 弱引用

## for of

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

JS - 6 - Set 和 WeakSet - 弱引用

# 案例

JS - 6 - Set 和 WeakSet - 弱引用

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

JS - 6 - Set 和 WeakSet - 弱引用

WeakSet

# 只能添加引用类型

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

JS - 6 - Set 和 WeakSet - 弱引用

# 基本用法

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

  • add
  • delete
  • has

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

主要,WeakSet 只能保存引用类型!

  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])) // 判断有误

JS - 6 - Set 和 WeakSet - 弱引用

# 特点:弱引用

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

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

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

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

JS - 6 - Set 和 WeakSet - 弱引用

## 弱引用

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

  1. 使用弱引用

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

    JS - 6 - Set 和 WeakSet - 弱引用

  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 
    

    JS - 6 - Set 和 WeakSet - 弱引用

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

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

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

JS - 6 - Set 和 WeakSet - 弱引用

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

JS - 6 - Set 和 WeakSet - 弱引用
甚至无法使用 size 属性 ( 下图 )

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

JS - 6 - Set 和 WeakSet - 弱引用

# 案例

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

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

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

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

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

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

JS - 6 - Set 和 WeakSet - 弱引用

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

相关标签: # ECMAscript 6