美文网首页
Set-WeakSet (es6)

Set-WeakSet (es6)

作者: 未路过 | 来源:发表于2022-10-07 10:18 被阅读0次

    数据结构:存放数据的方式
    js中Array可以使用下标,Map和Set不能使用下标。但是Array,Map,Set都属于iterable类型。使用iterable内置的forEach方法。

    1 Set的基本使用

    96.PNG
    // 1.创建Set结构
    const set = new Set();
    set.add(10);
    set.add(20);
    set.add(30);
    set.add(40);
    set.add(10);
    console.log(set);
    console.log(Object.prototype.toString.call(set))//[object Set]
    //set 结合 --》不允许数据的重复
    //Set(4) {10, 20, 30, 40}
    
    
    // 2.添加对象时特别注意:
    set.add({});
    set.add({});
    console.log(set);
    //Set(6) {10, 20, 30, 40, {…}, …}
    //两个空对象对应两个不同的内存地址,因此不是重复的数据
    
    
    const obj = {}
    set.add(obj)
    set.add(obj)
    
    console.log(set)
    //Set(7) {10, 20, 30, 40, {…},{…},{…}}
    //这时候obj是重复的,只能往set里面加一个
    
    // 3.对数组去重(去除重复的元素)
    const arr = [33, 10, 26, 30, 33, 26]
    //const newArr = [];
    /* for(let item of arr){
      console.log(newArr.indexOf(item));
      if(newArr.indexOf(item) == -1){
        newArr.push(item);
      }
    } */
    //console.log(newArr);//(4) [33, 10, 26, 30]
    
    //https://www.runoob.com/jsref/jsref-indexof-array.html
    
    
    const arrSet = new Set(arr);
    //可以放一个可迭代的对象作为参数
    
    console.log(arrSet);
    //Set(4) {33, 10, 26, 30}
    
    //如果想转换为一个数组的话
     //方法1:Array.from将类数组对象或可迭代对象转化为数组。
    const newArr = Array.from(arrSet)
    
    console.log(newArr);
    //(4) [33, 10, 26, 30]
    
    //方法2:展开语法(构造数组时)
    const newArr2 = [...arrSet]
    console.log(newArr2); //[object Array]
    //(4) [33, 10, 26, 30]
    
    
    

    2 Set的常见方法

    97.PNG
    const set = new Set()
    
    set.add(10)
    set.add(20)
    set.add(40)
    set.add(333)
    
    // 1.size属性 返回Set中元素的个数;
    
    console.log(set.size);//4
    
    
    // 2.Set的方法
    
    //add
    set.add(100);
    console.log(set);
    //Set(5) {10, 20, 40, 333, 100}
    
    
    //delete
    //把元素传进去
    set.delete(40);
    console.log(set);
    //Set(4) {10, 20, 333, 100}
    
    //has  有没有包含某个元素
    console.log(set.has(100)) //true
    
    
    //clear
    //set.clear()
    console.log(set);//Set(0) {size: 0}
    
    
    //3.对Set进行遍历
    //forEach(callback, [, thisArg]):通过forEach遍历set;
    
    set.forEach(item =>{
      console.log(item);
    })
    
    for( const item of set){
      console.log(item);
    }
    
    

    1 WeakSet的使用

    98.PNG
    强引用就是一个小孩A牵着一条狗,他们之间通过狗链儿连着
    
    弱引用就是,旁边有个小孩B指着A牵的狗,说:嘿,那有条狗,B指向那条狗,但他们之间没有是指绑在一起的东西
    
    当A放开狗链,狗就会跑掉(被垃圾回收),无论B是不是还指着
    
    但是,当B不再指着那条狗,狗还被A牵着,不会影响它是否跑掉
    
    1. 区别1
    // 1.区别一: 只能存放对象类型,不能存放基本数据类型
    
    // Uncaught TypeError: Invalid value used in weak set
    //weakSet.add(1)
    
    1. 区别2

      区别二: weakSet对对象是一个弱引用

      什么什么叫做弱引用?

      (1)原来对象在内存如果不再用,会被GC回收掉

      let obj = {

      name: "why"

      }

      obj不会被回收掉,因为obj指这这个对象。

      只要时从根对象开始,能找到某个对象,这个对象就不会被回收掉。

      {name:“why”}有个内存地址ox100,有个引用指向它,就是obj。通过let或者const创建出来的变量名称,是在VE里面,在ES5以前,VO对应的GO看成时根对象。但是有了VE之后,VE对应的VARIABLE,这个对象可以看成时根对象,这里的obj看成是在VE-》variable里面,es5之前VO里面的GO是根对象,es5之后,VE里面的variable_是根对象。

      根对象里面有个obj的属性指着(引用)这堆内存里面0x100地址的这个对象。

      垃圾回收期会不定时查看当前有哪些对象没有引用指向它,没有的话,这个对象到时候会被销毁掉。

      当前ox100这个地址的对象是不会被GC回收掉的,因为从根对象开始,有个引用指着它.

    100.PNG

    (2)

    let obj = {

    name: "why",

    friend:{

    name : "kobe"

    }

    }

    从根对象有引用指向ox100这个对象,所以ox100这个对象不会被销毁,

    在ox100这个对象里面有个引用指向ox200这个对象,所以ox200这个对象也不会被销毁

    这种情况,这两个对象都是不会被销毁的。

    101.PNG

    如果让obj.friend = null,这就意味着ox100里面的friend的值已经不是ox200了,叫做null了,对ox200的指向已经不存在了。可以把null理解成内存里面0x0的地方。这个空的地址。ox200就会被回收掉。

    如果obj=null,意味着,ve里面的variable_里面的obj指向空地址oxo,ox100这个对象也会被回收掉。

    回到最初,obj的指向ox100的这种引用,成为强引用(strong reference).在GC准备回收这个东西的时候,认为obj指向ox100这个线是有效的。

    弱引用叫做weak reference,虽然可能有一条引用,比如info也保存的是ox200, 然后我通过某种办法,让指向ox200这个对象的线是弱引用。GC是不会根据弱引用这条线判断的,就算有弱引用,没有强引用,也会被回收掉。

    可以通过弱引用使用对象里面的东西,打印里面的东西。

    102.PNG

    (3)可以把对象放到weakSet里面,但是创建出来的实例对对象的引用时弱引用。

    但是,set创建出来的实例对象对对象时强引用。

    set:内存表现

    这里的obj在VE里面。这时候,VE的variable_里面的属性obj指向ox100这个对象,所以ox100这个对象是不会被销毁的。接下来,new了一个新的set对象,set对象也是一个对象,地址时ox200。

    然后:set.add(obj), 不是直接把obj对象里面的内容放到set指向的对象里,而是把obj这个对象的地址放到set指向的这个对象里面。这时候,就多了一个引用,就是set指向的这个对象指向ox100. 这时候,这个ox100就相当于有两个被引用,

    103.PNG

    如果这时候让 obj = null, 相当于obj不再指向ox100这个对象,那么ox100这个对象会不会被销毁掉?

    是不会被销毁掉的,因为从set出发,也是从根对象出发,(VE的variable_里面的属性set)出发,有对ox100的引用。
    <img src="img/104.PNG" alt="alt" style="zoom:50%;" />

    因为0x100不会被销毁,所以set对对象的引用时一种强引用。

    (4) 如果时weakSet创建出来的对象,

    let obj = { 
      name: "why"
    }
    const weakSet = new weakSet()
    // 建立的是弱引用
    weakSet.add(obj)
    

    黄色的地方就变成了弱引用,如果obj=null,对ox100的引用也不存在了,那么GC到时候就会回收ox100这个对象
    <img src="img/105.PNG" alt="alt" style="zoom:50%;" />

    2 WeakSet的应用

    99.PNG
    // 3.WeakSet的应用场景
    const personSet = new WeakSet()
    class Person {
      constructor() {
        personSet.add(this)
      }
    
      running() {
        if (!personSet.has(this)) {
          throw new Error("不能通过非构造方法创建出来的对象调用running方法")
        }
        console.log("running~", this)
      }
    }
    
    let p = new Person()
    p.running()
    p = null
    
    p.running.call({name: "why"})
    

    为什么不能用set

    // 3.WeakSet的应用场景
    const personSet = new Set()
    class Person {
      constructor() {
        personSet.add(this)
      }
    
      running() {
        if (!personSet.has(this)) {
          throw new Error("不能通过非构造方法创建出来的对象调用running方法")
        }
        console.log("running~", this)
      }
    }
    
    let p = new Person()
    
    p.running()
    
    
    p.running.call({name: "why"})
    
    //p = null
    //为什么不能用set呢
    //personSet.add(this)
    //this(创建出来的p实例)会被强引用,如果有一天p=null,那么p指向的那个对象也不会被销毁
    //因为被personSet强引用,
    //这个p指向的对象不会被销毁的
    //导致===》就算想销毁p也销毁不掉
    //只能p=null之后,personSet.delete(p),才能让p指向的对象被回收
    
    

    相关文章

      网友评论

          本文标题:Set-WeakSet (es6)

          本文链接:https://www.haomeiwen.com/subject/ksbiartx.html