zoukankan      html  css  js  c++  java
  • 10-map/WeakMap/WeakSet的使用场景

    set数据结构:

    1.去重&&使用...运算符:

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

    2.Set可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)

    let a = new Set([1, 2, 3]);
    let b = new Set([4, 3, 2]);
    
    // 并集
    let union = new Set([...a, ...b]);
    // Set {1, 2, 3, 4}
    
    // 交集
    let intersect = new Set([...a].filter(x => b.has(x)));
    // set {2, 3}
    
    // 差集
    let difference = new Set([...a].filter(x => !b.has(x)));
    // Set {1}
     3.Array.from 方法可以将 Set 结构转为数组。

    WeakSet数据结构:

    WeakSet结构与Set类似,也是不重复的值的集合
    两个特点:
    1.WeakSet的成员只能是对象
    2.WeakSet中的对象都是弱引用,即垃圾回收机制不考虑WeakSet对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于WeakSet之中。
    关于弱引用,两个应用场景:
    1.定义类的时候
    const requests = new WeakSet();
    class ApiRequest {
      constructor() {
        requests.add(this);
      }
      makeRequest() {
        if(!request.has(this)) throw new Error("Invalid access");
        // do work
      }
    }

    2.创建DOM时候

    为了让垃圾回收程序回收元素的内存,可以在这里使用 WeakSet:
    const disabledElements = new WeakSet(); 
    const loginButton = document.querySelector('#login'); // 通过加入对应集合,给这个节点打上“禁用”标签 disabledElements.add(loginButton); 这样,只要 WeakSet 中任何元素从 DOM 树中被删除,垃圾回收程序就可以忽略其存在,而立即释放其内存(假设没有其他地方引用这个对象)。

    Map数据结构:

    它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应,是一种更完善的Hash结构实现。如果你需要“键值对”的数据结构,Map比Object更合适。

    作为构造函数,Map也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
    var map = new Map([
      ['name', '张三'],
      ['title', 'Author']
    ]);
    
    map.size // 2
    map.has('name') // true
    map.get('name') // "张三"
    map.has('title') // true
    map.get('title') // "Author"

    上面代码在新建Map实例时,就指定了两个键nametitle

    注意,只有对同一个对象的引用,Map结构才将其视为同一个键。这一点要非常小心。
    var map = new Map();
    map.set(['a'], 555);
    map.get(['a']) // undefined

    Map结构转为数组结构,比较快速的方法是结合使用扩展运算符(...)。

    let map = new Map([
      [1, 'one'],
      [2, 'two'],
      [3, 'three'],
    ]);
    
    [...map.keys()]
    // [1, 2, 3]

    Map数据结构项目应用场景:

    在一些 Admin 项目中我们通常都对个人信息进行展示,比如将如下信息展示到页面上。传统方法如下:

    HTML代码:

    <div class="info-item">
      <span>姓名</span>
      <span>{{info.name}}</span>
    </div>
    <div class="info-item">
      <span>年龄</span>
      <span>{{info.age}}</span>
    </div>
    <div class="info-item">
      <span>性别</span>
      <span>{{info.sex}}</span>
    </div>
    <div class="info-item">
      <span>手机号</span>
      <span>{{info.phone}}</span>
    </div>
    <div class="info-item">
      <span>家庭住址</span>
      <span>{{info.address}}</span>
    </div>
    <div class="info-item">
      <span>家庭住址</span>
      <span>{{info.duty}}</span>
    </div>

    JS代码:

    mounted() {
      this.info = {
        name: 'jack',
        sex: '男',
        age: '28',
        phone: '13888888888',
        address: '广东省广州市',
        duty: '总经理'
      }
    }

    我们通过 Map 来改造,将我们需要显示的 label 和 value 存到我们的 Map 后渲染到页面,这样减少了大量的html代码

    HTML代码:

    <template>
      <div id="app">
        <div class="info-item" v-for="[label, value] in infoMap" :key="value">
          <span>{{label}}</span>
          <span>{{value}}</span>
        </div>
      </div>
    </template>

    JS代码:

    data: () => ({
      info: {},
      infoMap: {}
    }),
    mounted () {
      this.info = {
        name: 'jack',
        sex: '男',
        age: '28',
        phone: '13888888888',
        address: '广东省广州市',
        duty: '总经理'
      }
      const mapKeys = ['姓名', '性别', '年龄', '电话', '家庭地址', '身份']
      const result = new Map()
      let i = 0
      for (const key in this.info) {
        result.set(mapKeys[i], this.info[key])
        i++
      }
      this.infoMap = result
    }

    WeakMap数据结构:

    WeakMap结构与Map结构基本类似:
    1.唯一的区别是它只接受对象作为键名(null除外),
    2.不接受其他类型的值作为键名,而且键名所指向的对象,不计入垃圾回收机制。
    应用场景1:
    var wm = new WeakMap();
    var element = document.querySelector(".element");
    
    wm.set(element, "Original");
    wm.get(element) // "Original"
    
    element.parentNode.removeChild(element);
    element = null;
    wm.get(element) // undefined

    上面代码中,变量wm是一个WeakMap实例,我们将一个DOM节点element作为键名,然后销毁这个节点,element对应的键就自动消失了,再引用这个键名就返回undefined

    应用场景2:注册监听事件的listener对象很适合用WeakMap来实现
    // 代码1
    ele1.addEventListener('click', handler1, false);
    ele2.addEventListener('click', handler2, false);
     
    // 代码2
    const listener = new WeakMap();
     
    listener.set(ele1, handler1);
    listener.set(ele2, handler2);
     
    ele1.addEventListener('click', listener.get(ele1), false);
    ele2.addEventListener('click', listener.get(ele2), false);

    代码2比起代码1的好处是:由于监听函数是放在 WeakMap 里面,则一旦dom对象ele1,ele2消失,与它绑定的监听函数handler1和handler2 也会自动消失
    应用场景3:部署私有属性

    let _counter = new WeakMap();
    let _action = new WeakMap();
    
    class Countdown {
      constructor(counter, action) {
        _counter.set(this, counter);
        _action.set(this, action);
      }
      dec() {
        let counter = _counter.get(this);
        if (counter < 1) return;
        counter--;
        _counter.set(this, counter);
        if (counter === 0) {
          _action.get(this)();
        }
      }
    }
    
    let c = new Countdown(2, () => console.log('DONE'));
    
    c.dec()
    c.dec()

    上面代码中,Countdown类的两个内部属性_counter_action,是实例的弱引用,所以如果删除实例,它们也就随之消失,不会造成内存泄漏。

  • 相关阅读:
    利用HttpClient进行带参数的http文件上传
    使用mysqlproxy 快速实现mysql 集群 读写分离 [转]
    SQL Server Express 自动备份方法
    screen 配置文件
    linux启动DHCP
    dynamic table_name in cursor
    LogMiner and supplemental logging
    RAC 规划配置网络环境
    RAC prepare OS and installation media
    一次导数据流程
  • 原文地址:https://www.cnblogs.com/haoqiyouyu/p/14775549.html
Copyright © 2011-2022 走看看