Map
Object
实质上是键值对的汇合(Hash 构造),但 Object
只能将字符串当做键,这就给 Object
带来了很大的限度。
let data = {}
let s = {name : '东方不败'}
data[s] = '东方求败'
// 如果键传入非字符串的值,会主动为字符串
console.log(data); // {[object Object]: '东方求败'}
console.log(data['[object Object]']); // 东方求败
为了解决这个问题,es6
提供了 Map
数据结构。它相似于对象,也是键值对汇合,但键 不局限于字符串
,各种类型的值都能够当做键。
- Object 构造:
字符串键: 值
- Map 构造:
值键: 值
let data2 = new Map()
let s2 = {name : "艺术概论"}
data2.set(s2,'中国工艺美术史')
console.log(data2.get(s2)); // 中国工艺美术史
console.log(data2); // key: {name: '艺术概论'} , value : "中国工艺美术史"
下面案例应用 Map
的set
办法,将 s2
当做 data2
的键,应用 get
办法取值。
Map 的一些罕用办法
办法 | 阐明 |
---|---|
set() | 为 Map 对象增加一个指定键(key)和值(value)的新元素 |
get() | 用来获取 Map 对象中指定的元素 |
has() | 返回 boolean 值,用来表明 Map 中是否存在该元素 |
delete() | 删除对应元素 |
size | 返回 Map 的成员数 |
clear() | 革除 Map 所有成员,没有返回值 |
let data2 = new Map()
let s2 = {name : "艺术概论"}
data2.set(s2,'中国工艺美术史')
data2.size; // 1
data2.has(s2); // treu
data2.delete(s2); // true
data2.has(s2); // false
data2.clear(); // undefined
Map 参数
Map
能够接管数组作为参数,数组的成员是 单个单个
的键值对的数组
let map = new Map([['name','东方不败'],
['title','东方求败']
])
console.log(map.size); // 2
console.log(map); // {"name" => "东方不败"},{"title" => "东方求败"}
console.log(map.has('name')); // true
console.log(map.get('name')); // 东方不败
留神:如果有多个雷同的键,前面的键值会笼罩后面的键值
不仅是数组,任何具备 Iterator
接口、且每个成员都是一个 双元素的数组
的数据结构,都能够当做 Map
构造函数的参数,Set
和 Map
也能够用来生成新的Map
Set 作为参数
let set = new Set([['a',1],['b',2]])
let m = new Map(set)
console.log(m); // {'a' => 1, 'b' => 2}
console.log(m.get('a')); // 1
Map 作为参数
let map2 = new Map([['text','世界古代设计史'],['name','王受之']])
let m2 = new Map(map2)
console.log(m2); // {'text' => '世界古代设计史', 'name' => '王受之'}
console.log(m2.get('text')); // 世界古代设计史
console.log(m2.get('hello')); // 读取不存在的键会返回 undefined
Map
只有对同一个对象的援用才视为同一个键
let map3 = new Map()
map3.set(['a',100])
console.log(map3.get(['a'])); // undefined
因为数组不是援用类型,生成多个数组,它们的内存地址是不一样的,其实就是根底数据类型和援用数据类型的利用,这里的两个 ['a']
看似是一样的,其实它们根本就是两个不同的值,Map
只有对同一个对象的援用才视为同一个键,没有读取到所以返回undefined
。请看上面的例子
let map4 = new Map()
let b = ['b']
let b2 = ['b']
map4.set(b)
console.log(map4.get(b2)); // undefined
Map
的值其实是跟内存地址绑定的,内存地址不同,那么键就不同(即便名字截然不同),在这里Map
就解决了同名属性抵触的问题,当咱们应用他人的库时,应用对象名当做键,就不同放心本人的属性与他人的属性雷同了。
如果 Map
的键是一个简略数据类型的值,如:number、string、boolean
,只有这两个值严格相等,Map
就视为同一个键,例如:0
和 -0
就是同一个键,而布尔值 true
和字符串 true
就是不同的键,此外 null
和undefined
也是不同的键。NaN
视为同一个键。
let n = new Map()
n.set(0,100)
console.log(n.get(-0)); // 100
n.set(5,123)
console.log(n.get('5')); // undefined
n.set(true,100)
console.log(n.get(1)); // undefined
n.set(NaN,123)
console.log(n.get(NaN)); // 123
n.set(null,100)
console.log(n.get(null)); // 100
console.log(n.get(undefined)); // undefined
Map 遍历办法
Map
提供三个遍历器生成函数和一个遍历办法
办法 | 阐明 |
---|---|
Map.prototype.keys() | 返回键名的遍历器。 |
Map.prototype.values() | 返回键值的遍历器。 |
Map.prototype.entries() | 返回所有成员的遍历器。 |
Map.prototype.forEach() | 遍历 Map 的所有成员。 |
定义数据
let m3 = new Map([['a',100],
['b',200],
['c',300]
])
keys
/* keys */
for(let k of m3.keys()){console.log(k); // a b c
}
values
/* values */
for(let k of m3.values()){console.log(k); // 100 200 300
}
entries
for(let k of m3.entries()){console.log(k); // ['a', 100] ['b', 200] ['c', 300]
console.log(k[0],k[1]); // a 100 b 200 c 300
}
// 或
for(let [k,v] of m3.entries()){console.log(k,v); // a 100 b 200 c 300
}
forEach
m3.forEach(el => console.log(el)) // 100 200 300
m3.forEach((val,index) => console.log(val,index)) // 100 'a' 200 'b' 300 'c'
Map 数据结构转换
Map 转数组
应用扩大运算符将 Map
构造转换为数组
let a = new Map([['a',1],
['b',2],
['c',3]
])
console.log([...a.keys()]); // ['a','b','c']
console.log([...a.values()]); // [1,2,3]
console.log([...a.entries()]); // ['a', 1] ['b', 2] ['c', 3]
console.log([...a]); // ['a', 1] ['b', 2] ['c', 3]
转换后的数组是一个真正的数组,能够应用数组办法
let back = [...a].filter((val,index) => val[1] == 2 )
console.log(back); // ['b',2]
数组转 Map
let a2 = new Map([['name','东方不败'],
[{num : 3},['abc']]
])
console.log(a2); // 0: {"name" => "东方不败"} 1: {Object => Array(1)}
Map 转对象
let a3 = new Map()
.set('a',100)
.set('b',200)
/* 通过函数传入 map */
function mapToObj(mapVal){
// 在外部创立一个空对象
let obj = {}
// 遍历 map 构造,给空对象赋值
for([k,v] of mapVal){obj[k] = v
}
return obj
}
let mObj = mapToObj(a3)
console.log(mObj); // {a: 100, b: 200}
如果有非字符串键名,会被转换成字符串再创建对象键名
对象转 Map
let obj = {'a':123,'b':456}
let mObj2 = new Map(Object.entries(obj))
console.log(mObj2); // {'a' => 123, 'b' => 456}
Map 转 JSON
Map 转 JSON 须要辨别两种状况
1、Map 键名都是字符串
2、Map 键名有非字符串的状况
1、Map 键名都是字符串
能够写一个通用函数,用来将 Map 转为 JSON
let j = new Map()
.set('name','西方')
.set('text','不败')
// mapToObj 为下面创立的 Map 转对象的函数
let shiftStrJson = (mapVal) => JSON.stringify(mapToObj(mapVal))
console.log(shiftStrJson(j)); // '{"name":" 西方 ","text":" 不败 "}'
2、Map 键名有非字符串的状况
function shiftMaptoArrayJson(mapVal){return JSON.stringify([...mapVal])
}
let j2 = new Map()
.set('name','西方')
.set('text','不败')
let shiftStrJson2 = shiftMaptoArrayJson(j2)
console.log(shiftStrJson2); // '[["name"," 西方 "],["text"," 不败 "]]'
以上两种的转换后果:
JSON 转 Map
JSON 转 Map 须要辨别两种状况
1、Map 键名都是字符串
2、Map 键名有非字符串的状况
1、键名都是字符串
let strObj = '{"name":" 西方 ","text":" 不败 "}'
let strMap = new Map(Object.entries(JSON.parse(strObj)))
console.log(strMap); // {'name' => '西方', 'text' => '不败'}
2、键名有非字符串状况
let strObj2 = '[["name"," 西方 "],["text"," 不败 "]]'
let strMap2 = new Map(JSON.parse(strObj2))
console.log(strMap2); // {'name' => '西方', 'text' => '不败'}
案例源码:https://gitee.com/wang_fan_w/es6-science-institute
如果感觉这篇文章对你有帮忙,欢送点亮一下 star 哟