ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

10-map/WeakMap/WeakSet的使用场景

2021-05-17 03:01:18  阅读:284  来源: 互联网

标签:10 set Map counter WeakMap map new 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,是实例的弱引用,所以如果删除实例,它们也就随之消失,不会造成内存泄漏。

 

标签:10,set,Map,counter,WeakMap,map,new,WeakSet
来源: https://www.cnblogs.com/haoqiyouyu/p/14775549.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有