Map结构是一个键值对的集合,跟Object对象不同的是,Map结构的键名(key)可以是任何类型的值,而WeakMap结构的键名只允许是引用类型的值。它们都提供了各自的方法和属性供开发者使用:set、get、has、delete等相同的方法,其中Map结构还多了clear方法,size属性和一些用于遍历的方法:keys、values、entries、forEach
什么是Map
- 介绍什么是Map,就不得不说起Object对象,我们都知道Object对象是键值对的集合:
1
2//Object对象
{"name":"name","gender":1} - ES5中的key键名的类型要求一定是字符串,当然,ES6已经允许属性名的类型是Symbol
- 现在,ES6 提供了Map结构给我们使用,它跟Object对象很像,但是不同的是,它的key键名的类型不再局限于字符串类型了它可以是各种类型的值;可以说,它比Object对象更加灵活了,当然,也更加复杂了
Map的基本用法
Map结构提供了一个构造函数给我们,我们使用的时候需要用new来创建实例:
1
let m = new Map();
- 如果想要在创建实例的同时,初始化它的内容,我们可以给它传参,形式跟Set结构类型,都是需要用数组作为参数
1
2
3
4
5
6
7let m = new Map([
["name","name"],
["gender",1]
]);
console.log(m);
//打印结果:Map {"name" => "name", "gender" => 1} - 注意Map( )方法里面的参数,首先它是一个数组,而里面的内容也是由多个数组组成,“name”:“前端君”作为一个键值对,将它们装在一个数组里面,[“name”:“name”],另外一组键值对也一样:[“gender”:1 ]。这就是初始化一个Map结构实例的基本写法。
Map结构还提供了一些实例的属性和方法
set( )方法 添加一对键值对
- set( )方法作用:给实例添加一对键值对,返回map实例。
- set(key,value)
1
2
3
4
5
6
7
8
9
10
11let m = new Map();
//set方法添加
//添加一个string类型的键名
m.set("name","name");
//添加一个数字类型的键名
m.set(1,2);
console.log(m);
//打印结果:Map {"name" => "name", 1 => 2} - set方法的使用很简单,只需要给方法传入key和value作为键名和键值即可。注意:第三行代码中,我们传入的key是数字1,这就证明了,Map结构确实可以存储非字符串类型的键名,当然你还可以设置更多其它类型的键名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21//数组类型的键名
let map = new Map()
let arr = ['123']
map.set(arr,456 )
m.set([1],2);
//对象类型的键名
m.set({"name":"Zhangsan"},2);
//布尔类型的键名
m.set(true,2);
//Symbol类型的键名
m.set(Symbol('name'),2);
//null为键名
m.set(null,2);
//undefined为键名
m.set(undefined,2); - 以上6种类型值都可以作为键名,可以成功添加键值对
使用set方法的时候需要注意,如果设置一个已经存在的键名,那么后面的键值会覆盖前面的键值
1
2
3
4
5
6
7
8
9let m = new Map();
m.set("name","hello");
console.log(m);
//结果:Map {"name" => "hello"}
//再次设置name的值
m.set("name","world");
console.log(m);
//结果:Map {"name" => "world"} - 上面的案例,我们第一次把name的值设置为“hello”,当再次使用set方法设置name的值的时候,后者成功覆盖了前者的值,从此“hello” 变 “world”。
get( )方法
- get( )方法作用:获取指定键名的键值,返回键值。
1
2
3
4let m = new Map([["name","王磊"]]);
m.get("name");//结果:王磊
m.get("gender");//结果:undefined - get方法使用也很简单,只需要指定键名即可。获取存在对应的键值,如果键值对存在,就会返回键值;否则,返回undefined
delete( )方法
- delete( )方法作用:删除指定的键值对,删除成功返回:true,否则返回:false
1
2
3
4
5
6let m = new Map();
m.set("name","王磊");
//结果:Map {"name" => "王磊"}
m.delete("name");//结果:true
m.delete("gender");//结果:false - 我们使用delete方法,删除“name”的时候成功,返回了true。删除“gender”的时候,由于Map结构中不存在键名:“gender”,所以删除失败,返回false
clear( )方法
- 跟Set结构一样,Map结构也提供了clear( )方法,让你一次性删除所有键值对
1
2
3
4
5
6
7let m = new Map();
m.set("name","name");
m.set("gender",1);
m.clear();
console.log(m);
//打印结果:Map { }has( )方法
- has( )方法作用:判断Map实例内是否含有指定的键值对,有就返回:true,否则返回:false
1
2
3
4
5let m = new Map();
m.set("name","job");
m.has('name');//结果:true
m.has('age');//结果:false - Map实例中含有键名:name,就返回了true,键名age不存在,就返回false
size属性
- 其中一个常用的属性就是size:获取实例的成员数。
1
2
3
4
5let m = new Map();
m.set(1,3);
m.set('1','3');
m.size;//结果:2遍历取值
- Object对象能被for…in遍历,Map结构也不示弱,同样可以被遍历。我们可以使用ES6的新特性for…of来遍历它的键名或者键值
entries( )方法
- entries( )方法作用:返回实例的键值对遍历器。
1
2
3
4
5
6
7
8
9
10let m = new Map([
["name","job"],
["age",25]
]);
for(let [key,value] of m.entries()){
console.log(key+' '+value);
}
//打印结果:name job
// age 25 - 案例中的 m.entries( ) 返回键值对的遍历器,使用了for…of来遍历这个遍历器,得到的值分别赋值到key和value
keys( ) 和 values( ) 方法
- keys( )方法:返回实例所有键名的遍历器。
- values( ) 方法:返回实例所有键值的遍历器。
- 既然都是遍历器,那就用for…of把它们遍历出来吧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18let m = new Map([
["name","job"],
["age",25]
]);
//使用keys方法获取键名
for(let key of m.keys()){
console.log(key);
}
//打印结果:name
// age
//使用values方法获取键值
for(let value of m.values()){
console.log(value);
}
//打印结果:job
// 25forEach( )方法
1
2
3
4
5
6
7
8
9
10let m = new Map([
["name","job"],
["age",25]
]);
m.forEach(function(value,key){
console.log(key+':'+value);
});
//打印结果:name:job
// age:25WeakMap的基本用法
1
let wm = new WeakMap();
- 两者都是使用new来创建实例。如果添加键值对的话,我们同样是使用set方法,不过键名的类型必须要求是引用类型的值,
1
2
3
4
5
6
7
8
9
10
11
12
13let wm = new WeakMap();
//数组类型的键名
wm.set([1],2);
//对象类型的键名
wm.set({'name':'Zhangsan'},2);
//函数类型的键名
function fn(){};
wm.set(fn,2);
console.log(wm);WeakMap跟Map的区别
- 如果是普通的值类型则不允许。比如:字符串,数字,null,undefined,布尔类型
- 没有clear方法
- 没有size属性
- 不能遍历也就没有了keys、values、entries、forEach这4个方法
理由跟WeakSet结构一样:键名中的引用类型是弱引用,你永远不知道这个引用对象什么时候会被垃圾回收机制回收了,如果这个引用类型的值被垃圾机制回收了,WeakMap实例中的对应键值对也会消失。