es6之set集合和map集合

1.set集合和map集合

ES6中新增的数据存储结构,不同的场景使用不同的集合去存储数据。

2 set集合

1 创建

用于存储不重复的数据
创建set集合
```js
    const s1 = new Set(iterable)
    console.log(s1)
```

2 方法

实例方法:

  1. add() 添加数据
  2. has() 判断数据是否存在
  3. delete() 删除数据,返回值为是否删除成功
  4. clear() 清空集合
  5. size 集合长度 只读
  6. for…of forEach

根据set自己仿写set集合

class MySet{
    constructor(iterator = []){
        // 传递的内容必须是一个可迭代对象
        if(typeof iterator[Symbol.iterator] !== "function"){
            throw new TypeError(`您所提供的${iterator}不是一个可迭代对象`)
        }
        this._datas = [];
        for (const item of iterator) {
            // console.log(item)
            this.add(item)
        }
    }
    add(data){
        if(!this.has(data)){
            this._datas.push(data);
        }
        return this;

    }
    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(data,element)){
                this._datas.splice(i,1)
                return true
            }
        }
        return false
    }
    clear(){
        this._datas.length = 0
    }
    get size(){
        return this._datas.length
    }
    forEach(callback){
        for (const item of this._datas) {
            callback(item,item,this)
        }
    }
    *[Symbol.iterator](){
        for (const item of this._datas) {
            yield item
        }
    }
    isEqual(data1,data2){
        if(data1 === 0 && data2 === 0){
            return true
        }
        return Object.is(data1,data2)
    }
}

2 map集合

2.1 创建

以键值对的形式存储,存储键名不重复的数据
```js
    const map = new Map(iterable)
    console.log(map)
````

2.2 方法

实例方法:

  1. size 集合长度 只读
  2. set(键名,键值) 添加数据
  3. get(键名) 获取数据
  4. has() 判断数据是否存在
  5. delete() 删除数据,返回值为是否删除成功
  6. clear() 清空集合
  7. for…of forEach

根据map自己仿写map集合

class MyMap{
    constructor(iterator = []){
        if(typeof iterator[Symbol.iterator] !== "function"){
            throw new TypeError(`您所提供的${iterator}不是一个可迭代对象`)
        }
        this._datas = [];
        for (const item of iterator) {
            // item也是一个可迭代对象
            if(typeof item[Symbol.iterator] !== "function"){
                throw new TypeError(`您所提供的${item}不是一个可迭代对象`)
            }
            // this.set(item[0],item[1])
            const iterator = item[Symbol.iterator]()//["a",1]
            const key = iterator.next().value
            const value = iterator.next().value
            this.set(key,value)
        }
    }
    set(key,value){
        // console.log(key,value)
        const obj = this._getObj(key)//undefined  item
        if(obj){
            obj.value = value
        }else{
            this._datas.push({
                key : key,
                value : value
            })
        }
    }
    _getObj(key){
        // 判断键名是否重复
        for (const item of this._datas) {
            if(this.isEqual(key,item.key)){
                return item
            }
        }
    }
    isEqual(data1,data2){
        if(data1 === 0 && data2 === 0){
            return true
        }
        return Object.is(data1,data2)
    }
    get(key){
        const obj = this._getObj(key)//undefined {"b":2}
        if(obj){
            return obj.value
        }
        return undefined
    }
    get size(){
        return this._datas.length;
    }
    delete(key){
        for(let i = 0;i<this._datas.length;i++){
            const element = this._datas[i]
            if(this.isEqual(key,element.key)){
                this._datas.splice(i,1)
                return true
            }
        }
        return false
    }
    clear(){
        this._datas.length = 0;
    }
    has(key){
        return this._getObj(key) !== undefined;
    }
    forEach(callback){
        for (const item of this._datas) {
            callback(item.value,item.key,this)
        }
    }
    *[Symbol.iterator](){
        for (const item of this._datas) {
            yield [item.key,item.value]
        }
    }
}

3 WeakSet集合和weakMap

WeakMap
因为 WeakMap 实例不会妨碍垃圾回收,所以非常适合保存关联元数据。来看下面这个例子,其中

使用了常规的 Map:

const m = new Map();
const loginButton = document.querySelector(’#login’);
// 给这个节点关联一些元数据
m.set(loginButton, {disabled: true});
假设在上面的代码执行后,页面被 JavaScript 改变了,原来的登录按钮从 DOM 树中被删掉了。但

由于映射中还保存着按钮的引用,所以对应的 DOM 节点仍然会逗留在内存中,除非明确将其从映射中

删除或者等到映射本身被销毁。

如果这里使用的是弱映射,如以下代码所示,那么当节点从 DOM 树中被删除后,垃圾回收程序就

可以立即释放其内存(假设没有其他地方引用这个对象):

const wm = new WeakMap();
const loginButton = document.querySelector(’#login’);
// 给这个节点关联一些元数据
wm.set(loginButton, {disabled: true});
WeakSet
相比于 WeakMap 实例,WeakSet 实例的用处没有那么大。不过,弱集合在给对象打标签时还是有

价值的。

来看下面的例子,这里使用了一个普通 Set:

const disabledElements = new Set();
const loginButton = document.querySelector(’#login’);
// 通过加入对应集合,给这个节点打上“禁用”标签
disabledElements.add(loginButton);
这样,通过查询元素在不在 disabledElements 中,就可以知道它是不是被禁用了。不过,假如

元素从 DOM 树中被删除了,它的引用却仍然保存在 Set 中,因此垃圾回收程序也不能回收它。

为了让垃圾回收程序回收元素的内存,可以在这里使用 WeakSet:

const disabledElements = new WeakSet();
const loginButton = document.querySelector(’#login’);
// 通过加入对应集合,给这个节点打上“禁用”标签
disabledElements.add(loginButton);
这样,只要 WeakSet 中任何元素从 DOM 树中被删除,垃圾回收程序就可以忽略其存在,而立即

释放其内存(假设没有其他地方引用这个对象)。

猜你喜欢

转载自blog.csdn.net/qq_45256777/article/details/120936718