你真的了解ES6的Set,WeakSet,Map和WeakMap吗?

以前在学习 ES6 的时候,看到 SetMap,不知道其应用场景有哪些,只以为不少时候会用在数组去重和数据存储,后来慢慢才领悟到 Set 是一种叫作集合的数据结构,Map 是一种叫作字典的数据结构。javascript

本文在gitthub作了收录:github.com/Michael-lzg…html

Set

Set 自己是一个构造函数,用来生成 Set 数据结构。Set 函数能够接受一个数组(或者具备 iterable 接口的其余数据结构)做为参数,用来初始化。Set 对象容许你存储任何类型的值,不管是原始值或者是对象引用。它相似于数组,可是成员的值都是惟一的,没有重复的值。前端

const s = new Set()
[2, 3, 5, 4, 5, 2, 2].forEach((x) => s.add(x))
for (let i of s) {
  console.log(i)
}
// 2 3 5 4

Set 中的特殊值

Set 对象存储的值老是惟一的,因此须要判断两个值是否恒等。有几个特殊值须要特殊对待:vue

  • +0 与 -0 在存储判断惟一性的时候是恒等的,因此不重复
  • undefinedundefined 是恒等的,因此不重复
  • NaNNaN 是不恒等的,可是在 Set 中认为 NaNNaN 相等,全部只能存在一个,不重复。

Set 的属性:

  • size:返回集合所包含元素的数量
const items = new Set([1, 2, 3, 4, 5, 5, 5, 5])
items.size // 5

Set 实例对象的方法

  • add(value):添加某个值,返回 Set 结构自己(能够链式调用)。
  • delete(value):删除某个值,删除成功返回 true,不然返回 false
  • has(value):返回一个布尔值,表示该值是否为 Set 的成员。
  • clear():清除全部成员,没有返回值。
s.add(1).add(2).add(2)
// 注意2被加入了两次

s.size // 2

s.has(1) // true
s.has(2) // true
s.has(3) // false

s.delete(2)
s.has(2) // false

遍历方法

  • keys():返回键名的遍历器。
  • values():返回键值的遍历器。
  • entries():返回键值对的遍历器。
  • forEach():使用回调函数遍历每一个成员。

因为 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),因此 keys 方法和 values 方法的行为彻底一致。java

let set = new Set(['red', 'green', 'blue'])

for (let item of set.keys()) {
  console.log(item)
}
// red
// green
// blue

for (let item of set.values()) {
  console.log(item)
}
// red
// green
// blue

for (let item of set.entries()) {
  console.log(item)
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

Array 和 Set 对比

  • ArrayindexOf 方法比 Sethas 方法效率低下
  • Set 不含有重复值(能够利用这个特性实现对一个数组的去重)
  • Set 经过 delete 方法删除某个值,而 Array 只能经过 splice。二者的使用方便程度前者更优
  • Array 的不少新方法 mapfiltersomeevery 等是 Set 没有的(可是经过二者能够互相转换来使用)

Set 的应用

一、Array.from 方法能够将 Set 结构转为数组。webpack

const items = new Set([1, 2, 3, 4, 5])
const array = Array.from(items)

二、数组去重git

// 去除数组的重复成员
;[...new Set(array)]

Array.from(new Set(array))

三、数组的 mapfilter 方法也能够间接用于 Setgithub

let set = new Set([1, 2, 3])
set = new Set([...set].map((x) => x * 2))
// 返回Set结构:{2, 4, 6}

let set = new Set([1, 2, 3, 4, 5])
set = new Set([...set].filter((x) => x % 2 == 0))
// 返回Set结构:{2, 4}

四、实现并集 (Union)、交集 (Intersect) 和差集web

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}

weakSet

WeakSet 结构与 Set 相似,也是不重复的值的集合。vue-cli

  • 成员都是数组和相似数组的对象,若调用 add() 方法时传入了非数组和相似数组的对象的参数,就会抛出错误。
const b = [1, 2, [1, 2]]
new WeakSet(b) // Uncaught TypeError: Invalid value used in weak set
  • 成员都是弱引用,能够被垃圾回收机制回收,能够用来保存 DOM 节点,不容易形成内存泄漏。
  • WeakSet 不可迭代,所以不能被用在 for-of 等循环中。
  • WeakSet 没有 size 属性。

Map

Map 中存储的是 key-value 形式的键值对, 其中的 keyvalue 能够是任何类型的, 即对象也能够做为 keyMap 的出现,就是让各类类型的值均可以看成键。Map 提供的是 “值-值”的对应。

Map 和 Object 的区别

  1. Object 对象有原型, 也就是说他有默认的 key 值在对象上面, 除非咱们使用 Object.create(null)建立一个没有原型的对象;
  2. Object 对象中, 只能把 StringSymbol 做为 key 值, 可是在 Map 中,key 值能够是任何基本类型(String, Number, Boolean, undefined, NaN….),或者对象(Map, Set, Object, Function , Symbol , null….);
  3. 经过 Map 中的 size 属性, 能够很方便地获取到 Map 长度, 要获取 Object 的长度, 你只能手动计算

Map 的属性

  • size: 返回集合所包含元素的数量
const map = new Map()
map.set('foo', ture)
map.set('bar', false)
map.size // 2

Map 对象的方法

  • set(key, val): 向 Map 中添加新元素
  • get(key): 经过键值查找特定的数值并返回
  • has(key): 判断 Map 对象中是否有 Key 所对应的值,有返回 true,不然返回 false
  • delete(key): 经过键值从 Map 中移除对应的数据
  • clear(): 将这个 Map 中的全部元素删除
const m = new Map()
const o = { p: 'Hello World' }

m.set(o, 'content')
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // false

遍历方法

  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每一个成员
const map = new Map([
  ['a', 1],
  ['b', 2],
])

for (let key of map.keys()) {
  console.log(key)
}
// "a"
// "b"

for (let value of map.values()) {
  console.log(value)
}
// 1
// 2

for (let item of map.entries()) {
  console.log(item)
}
// ["a", 1]
// ["b", 2]

// 或者
for (let [key, value] of map.entries()) {
  console.log(key, value)
}
// "a" 1
// "b" 2

// for...of...遍历map等同于使用map.entries()

for (let [key, value] of map) {
  console.log(key, value)
}
// "a" 1
// "b" 2

数据类型转化

Map 转为数组

let map = new Map()
let arr = [...map]

数组转为 Map

Map: map = new Map(arr)

Map 转为对象

let obj = {}
for (let [k, v] of map) {
  obj[k] = v
}

对象转为 Map

for( let k of Object.keys(obj)){
  map.set(k,obj[k])
}

Map的应用

在一些 Admin 项目中咱们一般都对我的信息进行展现,好比将以下信息展现到页面上。传统方法以下。

<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代码

<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 结构相似,也是用于生成键值对的集合。

  • 只接受对象做为键名(null 除外),不接受其余类型的值做为键名
  • 键名是弱引用,键值能够是任意的,键名所指向的对象能够被垃圾回收,此时键名是无效的
  • 不能遍历,方法有 getsethasdelete

总结

Set

  • 是一种叫作集合的数据结构(ES6新增的)
  • 成员惟1、无序且不重复
  • [value, value],键值与键名是一致的(或者说只有键值,没有键名)
  • 容许储存任何类型的惟一值,不管是原始值或者是对象引用
  • 能够遍历,方法有:adddeletehasclear

WeakSet

  • 成员都是对象
  • 成员都是弱引用,能够被垃圾回收机制回收,能够用来保存 DOM 节点,不容易形成内存泄漏
  • 不能遍历,方法有 adddeletehas

Map

  • 是一种相似于字典的数据结构,本质上是键值对的集合
  • 能够遍历,能够跟各类数据格式转换
  • 操做方法有:setgethasdeleteclear

WeakMap

  • 只接受对象做为键名(null 除外),不接受其余类型的值做为键名
  • 键名是弱引用,键值能够是任意的,键名所指向的对象能够被垃圾回收,此时键名是无效的
  • 不能遍历,方法有 getsethasdelete

推荐文章

搭建一个 vue-cli4+webpack 移动端框架(开箱即用)
从零构建到优化一个相似vue-cli的脚手架
封装一个toast和dialog组件并发布到npm
从零开始构建一个webpack项目
总结几个webpack打包优化的方法
总结vue知识体系之高级应用篇
总结vue知识体系之实用技巧
总结vue知识体系之基础入门篇
总结移动端H5开发经常使用技巧(干货满满哦!)

关注的个人公众号不按期分享前端知识,与您一块儿进步!

相关文章
相关标签/搜索