JS Set 与 weakSet

Set

Set是 ES6 新增的一种集合类型,它是由一组无序且唯一(即不能重复)的项组成的,该数据结构使用了与有限集合相同的数学概念。

属性

每一个 Set 实例都有 size 属性,该属性表示该实例有多少个元素。

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

基本API

  • 构建 Set 集合

使用 new 关键字创建一个 Set 实例,可以接收一个一维数组,作为初始化的数据。

const set1 = new Set();

const set2 = new Set(["key", "val"]);
console.log(set2.size)//2

const set3 = new Set([]);
console.log(set3.has(undefined))//false
  • 新增值

创建实例后可以通过 add 方法添加值。可以一次添加多个值并且连续调用。

const set1 = new Set();
console.log(set1.size);//0

set1.add("key", "val");
console.log(set1.size);//1

set1.add("key1", "val1").add("key2", "key2");
console.log(set1.size);//3
  • 判断值是否存在

通过 has 方法判断该值是否存在 Set 实例中。存在返回 true,不存在返回 false。

const set = new Set(["key", "val"]);
console.log(set.has("key"))//true
console.log(set.has("key1"))//false
  • 删除值

通过 delete 方法删除值。传入要删除的值。要删除的值在实例中则删除并返回 true,否则返回 false。

const set = new Set(["key", "val"]);
console.log(set.delete("key"))//true
console.log(set.size);
console.log(set.delete("key1"))//false
  • 清空 Set 集合

通过 clear 方法清空 Set 实例的值。

const set = new Set(["key", "val"]);
console.log(set.size);//2
set.clear();
console.log(set.size);//0
  • SameValueZero 规则

Set 可以存储任何 JS 类型。 Set 使用 SameValueZero(类似于严格对象相等)来确定键值是否已存在。即便更改了对象属性也依然能够判断。

const obj = {}
const set = new Set([obj, "val"]);
console.log(set.has(obj), set.size);//true 2
obj.name = "123";
set.add(obj);
console.log(set.has(obj), set.size);//true 2

迭代

Set 能够按照键值对的插入顺序迭代输出。并且 Set 实例提供了一个迭代器以便能够通过特特定方法按顺序迭代。

  • entries

调用本方法会返回一个迭代器。迭代结果是一个二维数组,元素值都为每一项的值

const set = new Set([1, 2, 3, 4]);
for (let item of set.entries()) {
  console.log(item);
}

在这里插入图片描述

  • values | keys

这两个方法是一样的,调用方法会返回一个按照插入顺序的值的迭代器。并且是默认迭代器。所以可以使用扩展操作符,使用 for of 迭代 Map 实例时可以省略显示调用 values();

const set = new Set([1, 2, 3, 4]);
for (let item of set.values()) {
  console.log(item);
}
console.log("-----------");
for (let item of set) {
  console.log(item);
}
console.log("-----------");
console.log([...set]);

在这里插入图片描述

  • 不使用迭代器
    当然也可以不使用迭代器而是用回调的方式迭代,示例如下。回调函数的第一个参数是值,第二个参数是键。这里键和值是一样的。
const set = new Set([1, 2]);
set.forEach((val, key) => {
  console.log(key + ":" + val);
})

在这里插入图片描述
需要注意的是如果在迭代过程中修改给了每次迭代的结果,并不会影响映射关系,如下例

const set = new Set([1, 2]);
for (let item of set.values()) {
  item = 3;
  console.log(item);
}
console.log(set);

在这里插入图片描述
由输出结果可知在遍历的过程中使 item 的值为 3,因此输出两次 3,并没有改变 set 实例的值。

weakSet

weakSet 也是 ES6 新增的一种集合类型,它有如下特点:

  1. 键只能是 Object 类型或继承自 Object 类型,否则会抛出错误
  2. weakSet 实例对该键 Object 是弱引用(后边会详细讲),不会影响 JS 的垃圾回收
  3. weakSet 的基本 API 比 Set 的少了 clear(清空)方法,因为特点2,所以没有必要再持有该方法。
  4. weakSet 没有提供迭代其实例键值对的迭代器。因为特点2,所以 weakMap 实例中的键值对随时随地都有可能被销毁。
  5. weakSet 实例没有 size 属性
  6. weakMap 也可以像构建 Map 那样构建,也有 add、has、delete方法。

什么是弱引用

JS 有一种垃圾回收策略叫做引用计数,通俗理解就是声明一个对象后,JS 就会使用一个变量用来保存该对象被使用的次数,如果被使用次数为 0 ,那么 JS 就会销毁该对象,释放内存。

给个例子

const obj1 = { name: 1 }, obj2 = { name: 2 };
const set = new weakSet([obj1, obj2]);

这里弱引用的意思是当我实例化了一个 weakSet 集合 Set,并且使用 obj1 和 obj2 作为值存入 Set 中,那么此时 set 使用了 obj1 和 obj2,但是由于 set 是 weakSet 实例,所以 obj1 和 obj2 的被使用次数并不会加 1,那么一旦 obj1 和 obj2 又没有在别的地方被使用,JS 就会回收 obj1 和 obj2,set 就失去了值。

因此 weakSet 实例没有提供迭代器,因为也许你刚迭代完,该对象就被回收了,内存都被释放了,那么此时的迭代就没有了意义。也正因此 weakSet 舍弃了 clear API。并且即使能够访问 weakSet 实例也无法看到其存储的键值对。

还需要注意 weakSet 的好兄弟 Set 就不是这样,Set 实例对于键的应用是强引用,只要 Set 实例没被回收,那么其存储键值对就会一直存在,不会被 JS 私自回收。

我是孤城浪人,一名正在前端路上摸爬滚打的菜鸟,欢迎你的关注。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值