Set-WeakSet (es6)

2022-10-07  本文已影响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指向的对象被回收

上一篇下一篇

猜你喜欢

热点阅读