一、Map的基本用法
Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。 JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。 map数据结构存储的是对象解构,以键值对的方式存储。用法类似set。 ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
创建map结构
map是构造函数,传递参数只能是数组类型的键值形式。
let sm = [
[ "name" , "zhaojiamin" ] ,
[ "sex" , "女" ]
]
let maparr = new Map ( sm) ;
console. log ( maparr) ;
二、Maps 和 Objects 的区别
(1)一个 Object 的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。 (2)Map 中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。 (3)Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。 (4)Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
三、实例的属性和操作方法
1. size 属性
console. log ( maparr. size) ;
2. Map.prototype.set(key, value)
给map集合添加键值。 set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。 set方法返回的是当前的Map对象,因此可以采用链式写法。 注意对象是引用类型值的情况
3. Map.prototype.get(key)
get方法通过键获取值,如果找不到key,返回undefined。
4. Map.prototype.has(key)
has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
5. Map.prototype.delete(key)
delete方法根据键删除某个值,成功返回true。如果删除失败,返回false。
6. Map.prototype.clear()
let obj= { a: 1 } ;
maparr. set ( "age" , 20 ) ;
maparr. set ( { a: 1 } , 'asd' ) ;
maparr. set ( obj, 'asd' ) ;
maparr. set ( 1 , 'zjm' ) ;
console. log ( maparr) ;
console. log ( maparr. get ( "name" ) ) ;
console. log ( maparr. get ( "age" ) ) ;
console. log ( maparr. get ( { a: 1 } ) ) ;
console. log ( maparr. get ( obj) ) ;
console. log ( maparr. get ( 1 ) ) ;
console. log ( maparr. has ( "sex" ) ) ;
console. log ( maparr. delete ( "age" ) ) ;
console. log ( maparr) ;
maparr. clear ( ) ;
console. log ( maparr) ;
四、 map集合的遍历方法
Map 结构原生提供三个遍历器生成函数和一个遍历方法。
1. Map.prototype.keys():返回键名的遍历器。
console. log ( maparr. keys ( ) ) ;
for ( let key of maparr. keys ( ) ) {
console. log ( key) ;
}
2. Map.prototype.values():返回键值的遍历器。
console. log ( maparr. values ( ) ) ;
for ( let value of maparr. values ( ) ) {
console. log ( value) ;
}
3. Map.prototype.entries():返回所有成员的遍历器。
console. log ( maparr. entries ( ) ) ;
for ( let item of maparr. entries ( ) ) {
console. log ( item) ;
}
4. Map.prototype.forEach():遍历 Map 的所有成员。
maparr. forEach ( ( item ) => {
console. log ( item) ;
} )
maparr. forEach ( ( value, key, map ) => {
console. log ( value, key, map) ;
} )
for ( let item of maparr) {
console. log ( item) ;
}
五、与其他数据结构的互相转换
1. Map 与 Array的转换–Array.from
Map 构造函数可以将一个 二维 键值对数组转换成一个 Map 对象 使用 Array.from 函数可以将一个 Map 对象转换成一个二维键值对数组
var array = [ [ "key1" , "value1" ] , [ "key2" , "value2" ] ] ;
console. log ( array) ;
var myMap = new Map ( array) ;
console. log ( myMap) ;
var outArray = Array. from ( myMap) ;
console. log ( outArray) ;
2. Map 的克隆
var myMap1 = new Map ( [ [ "key1" , "value1" ] , [ "key2" , "value2" ] ] ) ;
var myMap2 = new Map ( myMap1) ;
console. log ( myMap2) ;
3. Map 的合并
合并两个 Map 对象时,如果有重复的键值,则后面的会覆盖前面的
var a = new Map ( [ [ 1 , 'one' ] , [ 2 , 'two' ] , [ 3 , 'three' ] , ] ) ;
var b = new Map ( [ [ 1 , 'uno' ] , [ 2 , 'dos' ] ] ) ;
console. log ( new Map ( [ ... a, ... b] ) ) ;
4. Map 转为数组
Map 转为数组最方便的方法,就是使用扩展运算符(…)。
console. log ( ... maparr) ;
5. 数组 转为 Map
let m2 = new Map ( [
[ true , 7 ] ,
[ { foo: 3 } , [ 'abc' ] ] ] ) ;
console. log ( m2) ;
6. Map 转为对象
如果所有 Map 的键都是字符串,它可以无损地转为对象。如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。
let obj = { } ;
for ( let item of maparr)
{
obj[ item[ 0 ] ] = item[ 1 ] ;
}
console. log ( obj) ;
7. 对象转为 Map
对象转为 Map 可以通过Object.entries()。
let obj1 = { "a" : 1 , "b" : 2 } ;
let map = new Map ( Object. entries ( obj1) ) ;
console. log ( map) ;
8. Map 转为 JSON
Map 转为 JSON 要区分两种情况。 一种情况是,Map 的键名都是字符串,可以先将map转为对象,再转为 JSON。
function strMapToObj ( strMap ) {
let obj = Object. create ( null ) ;
for ( let [ k, v] of strMap) {
obj[ k] = v;
}
return obj;
}
function strMapToJson ( strMap ) {
return JSON . stringify ( strMapToObj ( strMap) ) ;
}
let myMap = new Map ( ) . set ( 'yes' , true ) . set ( 'no' , false ) ;
console. log ( strMapToJson ( myMap) ) ;
另一种情况是,Map 的键名有非字符串,可以先将map转为数组,再转为 JSON。
function mapToArrayJson ( map ) {
return JSON . stringify ( [ ... map] ) ;
}
let myMap = new Map ( ) . set ( true , 7 ) . set ( { foo: 3 } , [ 'abc' ] ) ;
console. log ( mapToArrayJson ( myMap) ) ;
9. JSON 转为 Map
JSON 转为 Map,正常情况下,所有键名都是字符串。 但是,有一种特殊情况,整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组。这时,它可以一一对应地转为 Map。这往往是 Map 转为数组 JSON 的逆操作。
let json = { "a" : "1" , "b" : "2" , "c" : "3" } ;
let ay = [ ] ;
for ( let key in json)
{
console. log ( key) ;
ay. push ( [ key, json[ key] ] ) ;
}
console. log ( new Map ( ay) ) ;
六、WeakMap
WeakMap结构与Map结构类似,也是用于生成键值对的集合。
1.WeakMap与Map的区别
首先,WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。 其次,WeakMap的键名所指向的对象,不计入垃圾回收机制 (weakMap中对象如果被清除,js的垃圾回收机制 默认会回收)。
let weakmap= new WeakMap ( ) ;
console. log ( weakmap) ;
2.WeakMap的用途
WeakMap 与 Map 在 API 上的区别主要是两个,一是没有遍历操作(即没有keys()、values()和entries()方法),也没有size属性。 因为没有办法列出所有键名,某个键名是否存在完全不可预测,跟垃圾回收机制是否运行相关。这一刻可以取到键名,下一刻垃圾回收机制突然运行了,这个键名就没了,为了防止出现不确定性,就统一规定不能取到键名。二是无法清空,即不支持clear方法。因此,WeakMap只有四个方法可用:get()、set()、has()、delete()。