自学内容网 自学内容网

想品客老师的第四天:Set与WeakSet类型

Set

Set 对象允许你存储任何类型(无论是原始值还是对象引用)的唯一值。集合(set)中的元素只会出现一次,你可以按照插入顺序迭代集合中的元素。

声明set的方法

let set = new Set([1,2,3,4,5]);

set和array还有object的区别

set内对数据的唯一性的判断是严格模式判断,也就是说字符串'1'和数字1是不一样的

但是在对象里会被判定为一样,也就是字符串'1'和数字1是一样的:

let obj = {
            1: "hdcms",
            "1": "houdunren"
        };
        console.log(obj);//1:"houdunren"

同样的属性名会被后面的覆盖,所以打印不出前面的属性值

注意在对象里,如果属性名是一个对象的话,要加中括号

加中括号以后,对象名会被所属对象识别为一个字符串,所以此时想访问这个【对象里的对象】就需要在访问的时候把对象转为字符串:

    let obj = {
            1: "hdcms",
            "1": "houdunren"
        };

        console.log(obj);
        let hd = {
            [obj]: "后盾人"
        };
        console.log(hd[obj.toString()]);

 set储存的内容顺序:对于 add() 方法来说,就是调用 add() 方法时集合中不存在相同的元素的顺序,相同的就插不进去

let set = new Set();
set.add(1); // 成功插入 1
set.add(2); // 成功插入 2
set.add(1); // 1 已经存在,不会插入
set.add(3); // 成功插入 3
console.log(set); // 输出: Set { 1, 2, 3 }

Set元素检测与管理

set.size:返回set的大小

  let set = new Set([1, 2, 3, 4, 5])
        console.log(set.size)//5

set.has():判断是否有某个元素

 let set = new Set([1, 2, 3, 4, 5])
        console.log(set.has(1))//true

set.delete:删除元素,并且返回一个bool值,代表删除是否成功

 let set = new Set([1, 2, 3, 4, 5])
        console.log(set.delete(1))//true,删掉了
        console.log(set.has(1))//false,没有1
        console.log(set.size)//大小为4

set.values()也可以检测

 console.log(set.values())//SetIterator {2, 3, 4, 5}

set.claer()清空元素,无返回值

  console.log(set.clear())//清空,没有返回值,所以在这里打印为undefined
        console.log(set.values())//SetIterator {}

set的类型转换

set转数组

有时候set在使用了数组方法时会进行隐式转换:

let set = new Set(["hdcms", "houdunren"]);
console.log(Array.from(set))//['hdcms', 'houdunren'],转换为数组

点语法也可以转换set为数组:

 console.log([...set])//['hdcms', 'houdunren']

在对set进行一些操作的时候,把set变成数组再变回来也很方便:

let set = new Set("123456789")
        console.log([...set])

        set = new Set([...set].filter(function (item) {
            return item < 5//筛选小于5的
        }))
        console.log(set)//Set(4) {'1', '2', '3', '4'}

可以简写为箭头函数:

  let set = new Set("123456789")
  set = new Set([...set].filter(item=> item < 5))
  console.log(set)//Set(4) {'1', '2', '3', '4'}

数组转set

数组借用set去重:

  let arr = [1, 2, 3, 4, 1, 2, 3, 4, 1]
        arr = [...new Set(arr)]
        console.log(arr)// [1, 2, 3, 4]

遍历set

set.keys()、set.values()、还有二者相结合的set.entries()

要注意的是对于 Set 来说,键和值是相同的,因为 Set 只存储值,没有键。

 let set = new Set(["hdcms", "houdunren"]);
        console.log(set.keys())//{'hdcms', 'houdunren'}
        console.log(set.values())//{'hdcms', 'houdunren'}
        console.log(set.entries())//{'hdcms' => 'hdcms', 'houdunren' => 'houdunren'}

所以这三个打印出来一样

set.forEach()

 let set = new Set(["hdcms", "houdunren"]);
        set.forEach(function (value, key, set) {
            console.log(set);
        })//hdcms,houdunren

for of():

let set = new Set(["hdcms", "houdunren"]);
        for (const value of set) {
            console.log(value);
        }//hdcms,houdunren

demo:使用set处理关键词

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>后盾人</title>
    <style>
      body {
        padding: 200px;
      }
      ul {
        list-style: none;
        padding: 0;
        margin: 0;
        width: 200px;
      }

      li {
        border: solid 1px #ddd;
        padding: 10px;
      }
      li:nth-of-type(odd) {
        background: yellowgreen;
      }
    </style>
  </head>
  <body>
    <input type="text" name="hd" />
    <ul></ul>
  </body>
  <script>
    let obj = {
      data: new Set(),
      keyword(word) {
        this.data.add(word);
      },
      show() {
        let ul = document.querySelector("ul");
        ul.innerHTML = "";
        this.data.forEach(function(value) {
          ul.innerHTML += `<li>${value}</li>`;
        });
      }
    };
    let input = document.querySelector("[name='hd']");
    input.addEventListener("blur", function() {
      obj.keyword(this.value);
      obj.show();
    });
  </script>
</html>

可以根据显示的关键词,记录搜索次数最多的,称为网络热门关键词

set的并集、交集、差集算法

set1内是用户1学习的科目,set2内是用户2学习的科目,如何求他们的公共学习科目?

并集算法,使用展开运算符将这个两个set合并,合并返回的set是没有重复部分的:

      let set1 = new Set([1, 2, 3, 4, 5])
        let set2 = new Set([1, 2, 4, 6, 9])
        console.log(new Set([...set1, ...set2]));

但是这样有些1用户学习2用户不学习的科目也在里面了

可以通过这个方式获取set1和set2的公共部分

  let set1 = new Set([1, 2, 3, 4, 5])
        let set2 = new Set([1, 2, 4, 6, 9])
        console.log(new Set(
            [...set1].filter(function (item) {
                return set2.has(item)
            })
        ));

也就是交集算法

前面加个感叹号就是差集:

    let set1 = new Set([1, 2, 3, 4, 5])
        let set2 = new Set([1, 2, 4, 6, 9])
        console.log(new Set(
            [...set1].filter(function (item) {
                return !set2.has(item)
            })
        ));

相对于set1减去和set2的公共部分

WeakSet

WeakSet和set一样,也不能有重复的内容,而WeakSet是给引用类型用的set

前面学的给set的方法,WeakSet也可以用

let nodes = new WeakSet();
        let divs = document.querySelectorAll("div");
        divs.forEach(function (item) {
            nodes.add(item);
        });
        nodes.delete(divs[0]);
        console.log(nodes.has(divs[0]));//false
        console.log(nodes);//WeakSet {div, div}

引用类型的垃圾回收原理

这个这篇讲过👇

js:变量提升、作用域、解构、箭头函数-CSDN博客

 WeakSet弱引用特性

垃圾回收机制里提到引用类型,用一次计数加1

而weakSet不会:

    let hd = { name: "后盾人" };
    let edu = hd;
    let set = new WeakSet();
    set.add(hd);

上面的代码可以看见hd、edu、set都指向了【name:'后盾人'】,说明引用次数应该记为3

但是WeakSet是弱引用,他引用了跟没引用一样,此时计数仍为2

而且不光这么离谱,当hd=null,edu=null,也就是引用计数为0的时候,会垃圾回收,【name:'后盾人'】就被清空了,但是即使清空了,也不告诉WeakSet

 let hd = { name: "后盾人" };
        let edu = hd;
        let set = new WeakSet();
        set.add(hd);

        hd = null;
        edu = null;
        console.log(set)

能打出来,但什么都没有,weakSet以为里面应该有值,实际上什么都没有了

(你可以回来,但那里已经没有人了)

这种特性很容易在循环遍历的时候出问题,所以WeakSet禁用了很多循环遍历的方法,比如keys、values、entries

也会在获取大小的时候出问题,所以size方法也用不了

这种特性也导致在实行dom操作的时候,不用额外再去删weakset

WeakSet应用

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>后盾人</title>
  </head>
  <style>
    * {
      padding: 0;
      margin: 0;
    }
    body {
      padding: 100px;
    }
    ul {
      list-style: none;
      display: flex;
      width: 200px;
      flex-direction: column;
    }
    li {
      height: 30px;
      border: solid 2px #e67e22;
      margin-bottom: 10px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding-left: 10px;
      color: #333;
      transition: 1s;
    }
    a {
      border-radius: 3px;
      width: 20px;
      height: 20px;
      text-decoration: none;
      text-align: center;
      background: #16a085;
      color: white;
      cursor: pointer;
      display: flex;
      justify-content: center;
      align-items: center;
      margin-right: 5px;
    }
    .remove {
      border: solid 2px #eee;
      opacity: 0.8;
      color: #eee;
    }
    .remove a {
      background: #eee;
    }
  </style>

  <body>
    <ul>
      <li>houdunren.com <a href="javascript:;">x</a></li>
      <li>hdcms.com <a href="javascript:;">x</a></li>
      <li>houdunwang.com <a href="javascript:;">x</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 => {
            const parentElement = event.target.parentElement;
            if (this.lists.has(parentElement)) {
              parentElement.classList.add("remove");
              this.lists.delete(parentElement);
            } else {
              parentElement.classList.remove("remove");
              this.lists.add(parentElement);
            }
          });
        });
      }
    }
    new Todo().run();
  </script>
</html>


原文地址:https://blog.csdn.net/Au_ust/article/details/145292440

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!