作为ES6新增特性,Map是一种新的集合类型,与Object一样,它也是键值对的集合,但是两者还是存在差别的
Map基本API
创建map
const m = new Map()
set:添加键值对
const m = new Map()
m.set('name', 'khkkm')
console.log(m) //{ 'name' => 'khkkm' }
m.set('name', 'khkkn')
console.log(m) //{ 'name' => 'khkkn' }
m.set('age', 20).set('sex', '男')
console.log(m) //{ 'name' => 'khkkn', 'age' => 20, 'sex' => '男' }
使用set添加的新成员,键如果已经存在,后添加的键值会覆盖已有的键值。set方法,返回Map实例,因为可以串联多个操作。
get:通过键获取值
console.log(m.get('age'),m.get('grade')) //20 undefined
获取不存在的成员,返回undefined
has:判断是否有某个成员
console.log(m.has('age'),m.has('grade')) //true false
delete:删除
m.delete('sex')
console.log(m) //{ 'name' => 'khkkn', 'age' => 20 }
m.delete('grade')
console.log(m) //{ 'name' => 'khkkn', 'age' => 20 }
删除不存在的键,什么都不会发生
clear:清空
m.clear()
console.log(m) //{}
size:获取有几个键值对(属性)
console.log(m.size) //0
Map特点
Object只能使用数值、字符串或符号作为键,而Map可以使用任何Js数据类型作键
const m = new Map()
m.set('name', 'khkkm')
m.set(true, 'true')
m.set({}, 'object')
m.set(new Set([1, 2]), 'set')
m.set(undefined, 'undefined')
console.log(m)
{
'name' => 'khkkm',
true => 'true',
{} => 'object',
Set(2) { 1, 2 } => 'set',
undefined => 'undefined'
}
Map内部的判等方式基本上相当于使用严格相等(===),除了NaN,Map中的NaN等于NaN
const m = new Map()
const a = parseInt('a')
const b = parseFloat('b')
console.log(a, b, a === b)
m.set(a, '我是a的值')
m.set(b, '我是b的值')
console.log(m.get(a))
//NaN NaN false 我是b的值
与Object另一个差异,Map实例会维护键值对的插入顺序
const m = new Map()
m.set(1, 1)
m.set(4, 4)
m.set(3, 3)
m.set(2, 2)
console.log(m) //{ 1 => 1, 4 => 4, 3 => 3, 2 => 2 }
const obj = {}
obj[1] = 1
obj[4] = 4
obj[3] = 3
obj[2] = 2
console.log(obj) //{ '1': 1, '2': 2, '3': 3, '4': 4 }
Map迭代
//创建的同时初始化,可以给Map传入一个二维数组,但是必须要体现出键和值
const m = new Map([
['name', 'khkkm'],
['age', 18]
])
for (pairs of m) {
console.log(pairs)
}
[ 'name', 'khkkm' ]
[ 'age', 18 ]
//单独获取键
for (key of m.keys()) {
console.log(key)
}
name
age
//单独获取值
for (value of m.values()) {
console.log(value)
}
khkkm
18
//m.forEach(function(value,key,map){},this指向) value:值,key:键,map:m本身
m.forEach((val, key, map) => {
console.log(key + '=>' + val, map)
})
name=>khkkm Map(2) { 'name' => 'khkkm', 'age' => 18 }
age=>18 Map(2) { 'name' => 'khkkm', 'age' => 18 }
什么时候使用Map?
如果只是需要key->value的结构,或者需要数值、字符串或符号以外的值做键,使用Map更合适
强引用与弱引用
强引用:对象的引用在 JavaScript 中是强引用,也就是将一个引用对象通过变量或常量保存时,那么这个变量或常量就是强引用,这个对象就不会被回收。
弱引用:WeakMap和 WeakSet是在 JavaScript 使用弱引用唯一途径,将一个对象作为键添加到 WeakMap 或 WeakSet 中并不能防止这些对象被回收。
水平有限,代码例子举不出来。。。所以上图
变量1、变量2、Map都有着对某个Object实例对象的强引用,随着一个一个的被释放,最终某个Object实例对象失去了所有对它的强引用,然后它被垃圾回收了。
变量1、变量2、WeakMap都有着对某个Object实例对象的引用,随着强引用们被释放,最终某个Object实例对象失去了所有对它的强引用,然后它被垃圾回收了。
WeakMap
ES6新增“弱映射”,也是一种新的集合类型,weak描述的是垃圾回收程序对待“弱映射”中键的方式(即弱引用)
WeakMap基本API
const m = new WeakMap()
const user1 = { name: '张三', age: 20 }
const user2 = { name: '李四', age: 17 }
const user3 = { name: '王五', age: 21 }
m.set(user1, 'user11')
m.set(user2, 'user22').set(user3, 'user33')
console.log(m.get(user1)) //user11
console.log(m.has(user2)) //true
m.delete(user2)
console.log(m.has(user2)) //false
区别于Map,WeakMap的基本API仅有如上,它没有clear和size
WeakMap特点
1 WeakMap的键只能是Object或者继承自Object的类型,如上述代码所示,值的类型无限制。
2 “weak”,表示这些键不属于正式的引用,不会阻止垃圾回收。
3 不可迭代,因为弱映射中的键值对可能随时被销毁,所以没必要提供迭代的能力,也不用像clear一次性清空所有,所以也没有clear方法。
什么时候使用WeakMap?
由于WeakMap不会妨碍垃圾回收,所以它很适合应用于某元素用完就应该立即被释放的场景。