更多的集合类型

# 更多的集合类型

# set

set 用于存放不重复的数据集合。 创建方式:var set = new Set()

如果传入的数组中有重复数据,回默认去重

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

# set操作

  • add(data)set集合的末尾添加数据。(如果数据已存在于 set 集合中,则不会再添加一项。)

    • set 集合判断数据相同是使用 Object.is() (但是除了 +0 与 -0)
  • delete(data) 删除集合中的data

  • clear() 清空集合

  • has(data) 判断set 集合中是否存在data 数据。

  • size 得到集合中的成员数量。不允许赋值。

# set实现

class MySet {
  constructor(iterator = []) {
    // 判断是否是可迭代的对象
    if (typeof iterator[Symbol.iterator] != "function") {
      throw new TypeError("你提供的不是一个可迭代对象!");
    }
    this._datas = [];
    for (const item of iterator) {
      this.add(item);
    }
  }
  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++) {
      if (this.isEqual(data, this._datas[i])) {
        this._datas.splice(i, 1);
        return true;
      }
    }
    return false;
  }
  clear() {
    this._datas.length = 0;
  }
  isEqual(data1, data2) {
    if (data1 == 0 && data2 === 0) {
      return true;
    }
    return Object.is(data1, data2);
  }
  *[Symbol.iterator](){
    for(const item of this._datas){
        yield item;
    }
  }
  get size(){
    return this._datas.length;
  }
}

# Map集合

map集合专门用于存储多个键值对数据。

使用对象存储有以下问题:

  • 键名只能是字符串
  • 获取数据的数量不方便
  • 键名容易和原型上的名称冲突

# 如何创建 Map

const map = new Map() // 创建一个空的 Map

初始化Map需要传入一个数组,数组内成员为一个长度为2的数组,第一项为键名,第二项为键值。

const initMap = new Map([['a',1],['b',2],['c',3]]) // 

# 操作

  • size 获取 Map 的键值对的数量。
  • set(键,值) 设置一个键值对,键和值可以是任意类型。
    • 如果键存在,则修改。
    • 如果键不存在,则增加。
    • 比较键的方式和 Set 相同。均使用 Object.is 判断是否相同。
  • get(键) 根据键名得到对应的值。
  • has(键) 判断键是否存在。
  • delete(键) 删除指定的键。

# Map实现

class MyMap {
  constructor(iterator = []) {
    if (typeof iterator[Symbol.iterator] != "function") {
      throw new TypeError(iterator + "不是可迭代对象");
    }
    this._datas = [];
    for (const item of iterator) {
      if (typeof item[Symbol.iterator] != "function") {
        throw new TypeError(item + "不是可迭代对象");
      }
      const ite = item[Symbol.iterator]()
      const key = ite.next().value;
      const value = ite.next().value;
      this.set(key, value);
    }
  }
  _getObj(key) {
    for (const item of this._datas) {
      if (this.isEqual(item.key, key)) {
        return item;
      }
    }
    return undefined;
  }
  isEqual(data1, data2) {
    if (data1 === 0 && data2 === 0) {
      return true;
    }
    return Object.is(data1, data2);
  }
  set(key, value) {
    const obj = this._getObj(key);
    if (obj) {
      obj.value = value;
    } else {
      this._datas.push({ key, value });
    }
  }
  has(key) {
    return !!this._getObj(key);
  }
  get(key){
    const obj = this._getObj(key);
    if(obj){
        return obj.value;
    }
  }
  delete(key){
    for(var i = 0;i<this._datas.length;i++){
        const ele = this._datas[i];
        if(this.isEqual(ele.key,key)){
            this._datas.splice(i,1);
        }
    }
  }
  clear(){
    this._datas.length = 0;
  }
  *[Symbol.iterator](){
    for(const item of this._datas){
        yield [item.key,item.value]
    }
  }
}

# WeakSet && WeakMap

# WeakSet

与 set 基本完全相同

不同点:

  • 内部存储的对象地址不会影响垃圾回收。即对象引用消失,WeakSet中的成员也会消失。
  • 只能添加对象
  • 不能遍历、没有 size 属性、

# WeakMap

与 map 基本完全相同

不同点:

  • 键不会影响垃圾回收。
  • 键必须是对象。