热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ES6的Map和Set的使用,以及weakMap的一点理解

一、MapMap可以用来存储键值对,在一定程度上扩展了Object的内容。 1.Map的基本API创建新的Map实例创建一个空映射letmapnewMap()传入一个包含键值对组的

一、Map

Map可以用来存储键值对,在一定程度上扩展了Object的内容。

 


1. Map的基本API

创建新的Map实例

// 创建一个空映射
let map = new Map()
// 传入一个包含键值对组的可迭代对象,
// 传入的可迭代对象会按顺序插入到新的map实例里
let arr = [
['key1', 'val1'],
['key2', 'val2'],
['key3', 'val3']
]
let map1 = new Map(arr)
// 同样也可以是自定义的迭代对象

set(key, value) 添加新的键值对,返回一个一个映射实例(所以可以链式操作)

get(key) 根据键名返回对应的键值

size属性,返回当前存储的键值对数量

has(key) ,返回是否有当前传入的键名是否存在,返回boolean类型

delete(key), 删除指定的键值对

clear() 清空映射,删除全部的键值对

let m = new Map()
// 添加新的键值对
m.set('name', 'zhangsan')
.set('age', 20)
// 获取对应的键值
console.log(m.get(name));
// 确定键名是否在实例上
console.log(m.has('name'));
// 确定存储的键值对的数量
console.log(m.size);
// 删除指定的键值对
m.delete('name')
// 清空映射,删除全部的键值对
m.clear()

 

Map的一些迭代方法

在插入内容时,map实例会维护插入顺序,遍历出来的顺序是插入顺序,而object的遍历顺序可能不是插入顺序。所以下面三个方法作用是合object中一样的,只是map调用会按照键值对的插入顺序迭代

entries 与迭代map自身相同,map本身也是可迭代的


keys
values
不同于对象的方法

forEach 不同于数组的forEach方法,map的forEach方法回调函数里面的两个参数一个是value,一个是key,函数的第二个参数同数组方法,是回调函数内部this的值

let m = new Map([
['key1', 'value1'],
['key2', 'value2'],
['key3', 'value3']
])
m.forEach((value, key) => {
console.log(value, key);
})
// value1 key1
// value2 key2
// value3 key3

 

Map解决了Object的什么问题

Object只能使用数字(number),字符串(string),符号(Symbol),作为键名,Map可以使用任何类型作为建名。两者之间相同的是对键值都没有限制,object在用其他类型作为键值时会toString进行转换。所以当需要存储更多类型时,选用Map

 


选择Object和Map

 

内存方面

 

同样大小的内存,map比Object存的多,所以Map胜, 2. 插入时 插入时两种方式差不多,插入大量数据时,还是选择map 3. 查找速度 差异极小,使用连续整数作为属性时,调用浏览器可以进行优化,可能速度会高点 4. 删除性能 删除时,map更优

 


Set


基本api

创建新的Set实例

// 创建一个空集合
let s = new Set()
// 传入可迭代对象,包含插入到集合中的新元素
let s = new Set([1, 2, 3])

add(item) 添加新元素,类似map的set方法,返回一个新的实例,所以可以链式调用

has(item) 查询是否有指定元素

size 属性, 查看集合的元素数量

delete(item) 删除指定的元素,返回布尔值,表示是否存在要删除的元素

clear() 清除集合,删除所有元素

 


迭代

set在插入时也会维持顺序,按插入顺序迭代

keys()

values()

自身可迭代

三种操作结果相同,都是迭代出每个元素

for(let i of s.values()) {
console.log(i);
}
for(let i of s.keys()) {
console.log(i);
}
for(let i of s) {
console.log(i);
}

entries,产生包含两个集合中重复元素的数组

let s = new Set([1, 2, 3])
for(let i of s.entries()) {
console.log(i);
}
// [1, 1]
// [2, 2]
// [3, 3]

 

关于weakMap的理解,

weakMap根据名字就可以看出来,它是一种弱的map映射关系,即WeakMaps保持了对键名所引用的对象的弱引用,弱引用就是在任何时候都有可能被垃圾回收机制回收掉的引用。直接声明的对象如

let o = {} // 这样创建一个对象是强引用,强引用是不会被垃圾回收的
// 只有在设置了null时,才会被回收
o = null // 可以被垃圾回收了

当声明了一个对象,而Map又引用这个对象作为键名时

let o = {name: 'zhangsan'}
let m = new Map()
// map强引用了o作为键值
m.set(o, 1)
// 当设置o= null 时,只是清掉了o对对象的引用
// 但是m仍然引用着对象,所以并不能清除
// 想要被清除掉,首先得先delete(key) 然后在使用key= null,才能清除

由此,weakMap的作用就显现出来了,由于它的键值对是弱引用,若依,当对象key=null时,因为他本来键值就是弱引用,所以等到下一轮垃圾回收执行时,该引用对象就会被回收掉. 所以weakmap的作用就是保留了对键名所引用的对象的弱引用,即,如果键名所引用的对象不被其他变量引用,那么垃圾回收就会释放掉对象所占内存,因为弱引用随时都有可能被垃圾回收清除,垃圾回收机制执行实际不可预测,所以WeakMap也就不能够遍历,简单的例子来说明

当weakMap的键值没有被引用时

let wm = new WeakMap()
// 空对象没有被任何值引用,只是作为了键值
// 所以,直接会被垃圾回收掉,键值对被破坏,值本身也会被垃圾回收
wm.set({}, 1)
console.log( wm.get({})) // undefined

当值有被引用时

let wm = new WeakMap()
// 创建一个对象引用着key
let obj = {
key: {}
}
// 在实例里用key作为键值
wm.set(obj.key, 1)
// 可以访问该键值对
console.log(wm.get(obj.key)); // 1
// 当清除掉obj对key的引用时,在wm中也就没有了对应的键值对映射
obj.key = null
console.log(wm.get(obj.key)); // undefined

WeakMap的四个方法,


get()
set()
has()
delete()

Weak中的建只能是对象

https://www.98891.com/article-90-1.html


WeakMap的应用场景


1. 数据缓存

当我们需要在不修改原对象的情况下存储某些属性或者根据对象存储一些计算的值,而又不想关系这些值是否被回收掉时,可以使用WeakMap

// 比如说保存对象属性的长度的缓存
const cache = new WeakMap()
function keyLength(obj) {
// 如果当前缓存中有这个数据就直接返回
if(cache.has(obj)) {
return cache.get(obj)
} else {
// 如果没有,就把当前对象的键的长度存在缓存中
const count = Object.keys(obj).length
cache.set(obj, count)
// 返回这次计算的长度
return count
}
}

2. dom中的数据

有时候可能会对dom节点关联一些数据,比如是否禁用什么的,可以用映射使他们关联起来,但是如果有一些操作可能需要删除掉这个dom节点,这个时候如果用普通的map的话,dom节点虽然删除了,但是他仍然在map中被引用着,所以耗费内存,这时,使用weakMap就能实现,如下。

let wm = new WeakMap()
const btn = document.querySelector('#btn')
// 给btn节点添加一些关联数据等
m.set(btn, {disabled:true})


推荐阅读
  • Sets和数组一样,都是一些有序值的的集合,但是Sets和数组又有所不同,首先Sets集合中不能存有相同的值,如果你向Set ... [详细]
  • idea Terminal配置cmder(增加nodejs,git配置,jdk本地环境)
    下载安装nodejs,git,cmder(绿色版直接解压)配置nodejs环境配置缓存npmconfigsetcacheE:\JetBrains\nodejs\node_c ... [详细]
  • 1、概念共享内存:共享内存是进程间通信中最简单的方式之一。共享内存允许两个或更多进程访问同一块内存,就如同malloc()函数向不同进程返回了指向同一个 ... [详细]
  • 在开发四国军棋的游戏中,通过flex联机游戏开发-四国军棋游戏(五)-提炼棋类开发api,我们提炼出了第一个关于棋类游戏开发的api-FlexChessAPI,这个a ... [详细]
  • JavaScript语言自身只有字符串数据类型,没有二进制数据类型。但在处理像TCP流或文件流时,必须使用到二进制数据。因此在Node.js中&#x ... [详细]
  • cp.php这四个,那么我们如何根据你访问的URL判断涉及到那些PHP文件和模板文件,方便您的进一步修改!好了,现在我们以最 ... [详细]
  • FF——————————–直接使用document.creatRange()来创建一个选区;默认是空的;使用selectNode(obj)来代替moveToElementText ... [详细]
  • Lodash中文文档(v3.10.1)–“Collection”要领TranslatedbyPeckZegOriginalDocs:Lodashv3.10.1Docs乞助翻译文档的 ... [详细]
  • TLB 缓存延迟刷新漏洞 CVE201818281 解析 ... [详细]
  • handler机制_Handler机制与原理
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Handler机制与原理相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 缓存的重要性就不用再强调了,@OutputCache给我们提供了一种声明的方式(对应的还有编程的方式)来控制页面和用户控件的缓存策略,这是一种最简单直接的网站优化方式。还是先来过一遍@ ... [详细]
  • jquery调用网易云音乐API遇到,网易音乐接口需要用node启动前端js调用代码varthisUrlhttp:127.0.0.1:3000 ... [详细]
  • 史上最全的Websocket入门教程
    websocket是什么?答:它是一种网络通信协议,是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。为什么需要websocket?疑问?我 ... [详细]
  • SpringBoot与缓存使用及原理(上),Go语言社区,Golang程序员人脉社 ... [详细]
  • 人生的旅途,前途很远,也很暗。然而不要怕,不怕的人的面前才有路。——鲁迅自从上一篇博客发布后,已经有很长时间没有更新博客了,一直忙着支付通的事情,在此给大家道个歉。先贴个图:你不要惊讶 ... [详细]
author-avatar
lyglpp
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有