Map和WeakMap

Map可以用于存储键值对的数据。在ECMAScript6之前为了达到这种效果都是使用的Object对象。Map能够记住原始插入顺序,任何值(对象或原始值)都可作为键或值。

Map

基本API

可以通过new关键字和Map构造函数创建一个空的映射

const stringKey = 'key1'
const numberKey = 1
const symbolKey = Symbol('key')
//创建一个空的映射
const map = new Map()
//使用.size属性查看长度
console.log(map.size) //0
//查看是否有指定键对应的值
console.log(map.has(stringKey)) //false
//根据键返回值
console.log(map.get(stringKey)) //undefined
//使用.set添加值
map.set(stringKey, 'stringValue')
//允许链式调用
map.set(numberKey, 'numberValue').set(symbolKey, 'symbolValue')
//查看长度
console.log(map.size) //3
//根据键返回值
console.log(map.get(stringKey)) //"stringKey"
console.log(map.get(numberKey)) //"numberValue"
console.log(map.get(symbolKey)) //"symbolValue"
//打印map实例
console.log(map) //Map(3) {"key1" => "stringValue", 1 => "numberValue"} //可以发现Symbol的键没有打印出来,但是长度还是3,展开后是这样的,也能通过.get得到值
//0: {"key1" => "stringValue"}
//1: {1 => "numberValue"}
//2: "symbolValue"
//删除数据对
map.delete(numberKey)
console.log(map.has(numberKey)) //false
//清空map
map.clear()
console.log(map.size) //0

//也可以创建实例时就初始化
//接收一个可迭代的对象,需要包含键/值对数组, 可以使用任何 JavaScript 数据类型作为键
const initMap = new Map([
    [stringKey, 'stringValue'],
    [numberKey, 'numberValue'],
    [symbolKey, 'symbolValue']
])
console.log(initMap) //Map(3) {"key1" => "stringValue", 1 => "numberValue"}

Map内部使用SameValueZero比较操作(ECMAScript规范内部定义,语言中不能使用),基本上相当于使用严格对象相等的标准来检查键的匹配性,但比较也可能导致意想不到的冲突

const a = 0 / ''
const b = 0 / ''
const pz = +0
const nz = -0

const map = new Map([
    [a, '这是a的值'],
    [pz, '这是+0的值']
])

console.log(map.get(b)) //这是a的值
console.log(map.get(nz)) //这是+0的值

Map的顺序与迭代

Map会维持键值对的插入顺序

由于实现了iterator迭代器,可以使用values, keys, entries方法,会返回迭代器。

const map = new Map([
	['key1', 'value1'],
	['key2', 'value2']
])

//for...of返回[key, value]形式
for (const pair of map) {
	console.log(pair)
}
//["key1", "value1"]
//["key2", "value2"]

//Map.prototype.entries()返回[key, value]形式
for (const pair of map.entries()) {
	console.log(pair)
}
//["key1", "value1"]
//["key2", "value2"]

//Symbol.iterator属性返回[key, value]形式
for (const pair of map[Symbol.iterator]()) {
	console.log(pair)
}
//["key1", "value1"]
//["key2", "value2"]

//Map.prototype.keys()返回键
for (const k of map.keys()) {
	console.log(k)
}
//"key1"
//"key2"

//Map.prototype.values()返回值
for (const v of map.values()) {
	console.log(v)
}
//"value1"
//"value2"

//Map.prototype.forEach()
map.forEach(function (v, k) {
	console.log(k, v)
})
//"key1" "value1"
//"key2" "value2"

//支持扩展操作
console.log(...map)//["key1", "value1"] ["key2", "value2"]

//可以方便的复制或合并Map
//复制
const clone = new Map(map)
console.log(clone.get('key1'))
console.log(clone === map) //false
//合并
const anotherMap = new Map([
	[12, '12'],
	[34, '34']
])
const merged = new Map([...map, ...anotherMap])
console.log(merged.size) //4

键和值在迭代器遍历时是可以修改的,但映射内部的引用则无法更改

const m = new Map([
	['key1', 'value1']
])
//作为键的字符串原始值是不能修改的
for (let k of m.keys()) {
	k = 'key2'
	console.log(k) //"key2"
	console.log(m.get('key1')) //"value1"
}

WeakMap

WeakMap中的"weak"(弱)描述的是JavaScript垃圾回收程序对待”弱映射“中的键的方式。其键必须是对象,否则会报错。由于这种弱引用,WeakMapkey是不可枚举的。

const wm = new WeakMap()
const objectKey1 = {}
const objectKey2 = {key: '1'}
wm.set(objectKey1, 'value1')
  .set(objectKey2, 'value2')
console.log(wm.has(objectKey1)) //true
console.log(wm.get(objectKey1)) //'value1'

弱键

WeakMap中的键,只要没有引用再指向这个键,就将会被垃圾回收程序回收

const wm = new WeakMap()
wm.set({}, 'value') //由于这个对象没有引用指向它,会被当做垃圾回收

//另一个例子
const container = {
	key: {}
}
const wm2 = new WeakMap()

wm2.set(container.key, 'value')
console.log(wm2.has(container.key)) //true
container.key = null //执行这个以后这个键值对将会被垃圾回收程序清理掉了

既然都已经没有引用指向这个对象了,当然再用wm2.has(container.key)也没有意义,container.key指向的已经不是原来那个对象了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值