1

Set

Set类似于数组,但是Set中不存在重复元素。
Set可以接受一个数组(或者其他具有itarable接口的数据结构)作为参数

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

从上面的代码可以看出Set有去重的功能。[...new Set(arr)]
去重还有另一个方法,Array.from将Set数据结构的数据转换成数组。

function removelArr(arr) {
    return Array.from(new Set(arr));
}
removelArr([1, 1, 2, 3, 2, '1']);//[1, 2, 3, '1']
或者
[...new Set([1, 1, 2, 3, 2, '1'])];//[1, 2, 3, '1']

Set加入值的时候不会发生类型转变

const set = new Set([1,'1']);
console.log([...set]);//[1, '1']

Set内部判断两个值是否相同使用了Object.is(a, b)方法,这个方法与严格等于的不同之处在于NaNObject.is(NaN, NaN)返回的是true

let a = NaN;
let b = NaN;
let set = new Set();
set.add(a);
set.add(a);
console.log([...set]);//[NaN]

捎带提一下两个对象的总是不相等的,这就不用多说了吧,内存地址不同。。。

let obj1 = {};
let obj2 = {};
let set = new Set();
set.add(obj1);
set.add(obj2);
console.log([...set]);//[{}, {}]

Set的属性

  • size:获取成员个数

Set的方法

  • add(value):增加一个成员,返回值为set结构本身
  • delete(value):删除某个成员,返回值是一个布尔值,是否删除成功
  • clear():清空所有成员,无返回值
  • has(value):判断是否有某个成员,返回一个布尔值,是否存在某个元素

    let set = new Set();
    set.add(1).add(2).add(2).add('1');
    set.size;//3
    set.delete('1');//true
    set.size;//2
    set.has(2);//true
    set.clear();
    set.size;//0

Set的遍历操作

  • keys():返回键名的遍历器

    let set = new Set([1, 1, 2, 3, 2, '1']);
    //因为keys返回的是遍历器,所以可以使用`for...of`,数组没有键名只有键值,所以keys和values返回的是一致的
    for(let item of set.keys()){
        console.log(item);// 1 2 3 '1'
    }
  • values():返回值名的遍历器

    let set = new Set([1, 1, 2, 3, 2, '1']);
    //因为values返回的是遍历器,所以可以使用`for...of`
    for(let item of set.values()){
        console.log(item);// 1 2 3 '1'
    }
  • entries():返回键值对的遍历器

    //entries方法返回的遍历器,同时包括键名和键值
    let set = new Set([1, 1, 2, 3, 2, '1']);
    //因为values返回的是遍历器,所以可以使用`for...of`
    for(let item of set.entries()){
        console.log(item);// [1, 1] [2, 2] [3, 3] ['1', '1']
    }
  • forEach():使用回调函数遍历每个成员

    let set = new Set([1, 4, 9]);
    set.forEach((value, key) => console.log(key + ' : ' + value))
    // 1 : 1
    // 4 : 4
    // 9 : 9

Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。

Set.prototype[Symbol.iterator] === Set.prototype.values
//true

这意味着我们可以直接遍历Set

let set = new Set([1, 4, 9]);
for(let item of set) {
    console.log(item);//1 4 9
}

WeakSet

注意点:

  • WeakSet的成员只能是对象
  • WeakSet的成员是弱引用,随时都可能消失,所以无法遍历也就无法获取成员数量

WeakSet的方法

  • add(value)向 WeakSet 实例添加一个新成员。
  • delete(value)清除 WeakSet 实例的指定成员。
  • has(value)返回一个布尔值,表示某个值是否在 WeakSet 实例之中。

WeakSet 的一个用处,是储存 DOM 节点,而不用担心这些节点从文档移除时,会引发内存泄漏。

下面是 WeakSet 的另一个例子。

const foos = new WeakSet()
class Foo {
  constructor() {
    foos.add(this)
  }
  method () {
    if (!foos.has(this)) {
      throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!');
    }
  }
}

method只能通过Foo的实例调用不然就会抛出异常,当删除实例的时候,不用操作foos也不会引发内存泄露


Jason
90 声望3 粉丝