Set

  1. Set 有序无重复集合,类似数组,但成员的值都是唯一的;

  2. set 集合实现了 iterator 接口,所以可使用 「扩展运算符」「for…of…」 进行遍历;

Set 属性和方法

属性和方法 描述
size 返回集合的元素个数
has() 检测集合中是否包含某个元素,返回 boolean
add() 增加一个新元素,返回当前集合
delete() 删除元素,返回 boolean
clear() 清空集合,返回 undefined
keys() 得到 Set 实例中的键作为一个可以遍历的对象,键和值相等,可以使用 .next().value 取值
values() 得到 Set 实例中的值作为一个可以遍历的对象,可以使用 .next().value 取值
entries() 得到 Set 实例中的键值作为一个可以遍历的对象,可以使用 .next().value 取值

基本使用

JavaScript
JavaScript
JavaScript
JavaScript
JavaScript
// 创建一个非空集合
let s1 = new Set([1, 2, 3, 1, 2, 3]);

// 返回集合的元素个数
console.log(s1.size); // 3

// 添加新元素
console.log(s1.add(4)); // Set(4) {1, 2, 3, 4}

// 删除元素
console.log(s1.delete(1)); // true

// 检测是否存在某个值
console.log(s1.has(2)); // true

// 使用扩展运算符
console.log([...s1]); // [2, 3, 4]

// 清空集合
console.log(s1.clear());
var set = new Set([1, 2, 3, 4]);

var values = set.values()
console.log(values.next().value);  // 1
console.log(values.next().value);  // 2
console.log(values.next().value);  // 3
var set = new Set(['a', 'b', 'c'])

set.keys();    // SetIterator {"a", "b", "c"}
set.values();  // SetIterator {"a", "b", "c"}
set.entries(); // SetIterator {"a" => "a", "b" => "b", "c" => "c"}

for(var [key, value] of set.entries()) {
    console.log(key, value);
}
// a, a
// b, b
// c, c
// Set 转 Array

// 1. 使用扩展运算符(...)可以将 Set 数据结构转化数组形式
var set = new Set([1, 2, 3, 4]);
console.log([...set]); // [1,2,3,4]

// 2. Array.from() 进行转化数组
var set = new Set([1, 2, 3, 4]);
console.log(Array.from(set)); // [1,2,3,4]
// 数组去重
console.log([...new Set([1, 2, 2, 3, 4])]); // [1,2,3,4]
console.log(Array.form(new Set([1, 2, 2, 3, 4]))); // [1,2,3,4]

手写 set

class MySet {
  constructor(iterator = []) {
    // 验证是否是可迭代的对象
    if (typeof iterator[Symbol.iterator] !== "function") {
      throw new TypeError(`你提供的${iterator}不是一个可迭代的对象`);
    }
    this._datas = [];
    for (const item of iterator) {
      this.add(item);
    }
  }

  get size() {
    return this._datas.length;
  }

  add(data) {
    if (!this.has(data)) {
      this._datas.push(data);
    }
  }

  has(data) {
    for (const item of this._datas) {
      if (this.isEqual(data, item)) {
        return true;
      }
    }
    return false;
  }

  delete(data) {
    for (let i = 0; i < this._datas.length; i++) {
      const element = this._datas[i];
      if (this.isEqual(element, data)) {
        // 删除
        this._datas.splice(i, 1);
        return true;
      }
    }
    return false;
  }

  clear() {
    this._datas.length = 0;
  }

  *[Symbol.iterator]() {
    for (const item of this._datas) {
      yield item;
    }
  }

  forEach(callback) {
    for (const item of this._datas) {
      callback(item, item, this);
    }
  }

  /**
   * 判断两个数据是否相等
   * @param {*} data1
   * @param {*} data2
   */
  isEqual(data1, data2) {
    if (data1 === 0 && data2 === 0) {
      return true;
    }
    return Object.is(data1, data2);
  }
}

WeakSet

  1. WeakSet 存放的数据是一个弱引用类型,对元素的引用是弱引用,如果没有其他对象引用,GC 会对该对象进行回收;

  2. 不允许遍历,因为遍历的时候会有指针指向该对象,会对 GC 回收造成影响,所以存储带 weakSet 的数据是无法获取的,在现实开发中应用场景并不多;

方法

方法名 描述
add WeakSet 实例中添加值
delete 删除 WeakSet 实例中的指定值
has 查找指定的值是否在 WeakSet 实例中

基本使用

JavaScript
JavaScript
var ws = new WeakSet();
var obj1 = {};
var obj2 = {};

ws.add(obj1);
ws.add(obj2);

ws.has(obj1);   // true
ws.has(obj2);   // true

ws.delete(obj1); // 从 set 中删除 obj1 对象
ws.has(obj1);    // false, obj1 对象已经被删除了
ws.has(obj2);    // true, obj2 依然存在
let obj = { name: "zhangsan", age: 18 };
let obj2 = obj;
const set = new WeakSet();
set.add(obj);

obj = null;
obj2 = null;
console.log(set); // WeakSet 中存储的对象被 GC 回收了 

WeakSet VS Set

  1. 相同点WeakSetSet 都是有序无重复的数据结构;

  2. 不同点

    1. WeakSet 只能是对象的集合,而不能是任何类型的任意值,Set 可以存储任何类型的值;
    2. WeakSet 中存储的对象值都是被弱引用的,如果没有其他的变量或属性引用这个对象值,则这个对象值会被当成垃圾回收掉;正因为这样 WeakSet 对象是无法被枚举的,没有办法拿到它包含的所有元素;
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. Set
    1. 1.1. Set 属性和方法
    2. 1.2. 基本使用
    3. 1.3. 手写 set
  2. 2. WeakSet
    1. 2.1. 方法
    2. 2.2. 基本使用
    3. 2.3. WeakSet VS Set