翼度科技»论坛 编程开发 JavaScript 查看内容

Map数据结构详解

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
Map

Object本质上是键值对的集合(Hash结构),但Object只能将字符串当做键,这就给Object带来了很大的限制。
  1. let data = {}
  2. let s = {
  3.      name : '东方不败'
  4. }
  5. data[s] = '西方求败'
  6. // 如果键传入非字符串的值,会自动为字符串
  7. console.log(data);  // {[object Object]: '西方求败'}
  8. console.log(data['[object Object]']);  // 西方求败
复制代码
为了解决这个问题,es6提供了Map数据结构。它类似于对象,也是键值对集合,但键不局限于字符串,各种类型的值都可以当做键。

  • Object结构:字符串键:值
  • Map结构:值键:值
  1. let data2 = new Map()
  2. let s2 = {
  3.      name : "艺术概论"
  4. }
  5. data2.set(s2,'中国工艺美术史')
  6. console.log(data2.get(s2));  // 中国工艺美术史
  7. 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所有成员,没有返回值
  1. let data2 = new Map()
  2. let s2 = {
  3.    name : "艺术概论"
  4. }
  5. data2.set(s2,'中国工艺美术史')
  6. data2.size; // 1
  7. data2.has(s2);  // treu
  8. data2.delete(s2); // true
  9. data2.has(s2); // false
  10. data2.clear(); // undefined
复制代码
Map参数

Map可以接收数组作为参数,数组的成员是单个单个的键值对的数组
  1. let map = new Map([
  2.      ['name','东方不败'],
  3.      ['title','西方求败']
  4. ])
  5. console.log(map.size);  // 2
  6. console.log(map);  // {"name" => "东方不败"}, {"title" => "西方求败"}
  7. console.log(map.has('name')); // true
  8. console.log(map.get('name')); // 东方不败
复制代码

注意:如果有多个相同的键,后面的键值会覆盖前面的键值
不仅是数组,任何具有Iterator接口、且每个成员都是一个双元素的数组的数据结构,都可以当做Map构造函数的参数,Set和Map也可以用来生成新的Map
Set作为参数
  1. let set = new Set([['a',1],['b',2]])
  2. let m = new Map(set)
  3. console.log(m); // {'a' => 1, 'b' => 2}
  4. console.log(m.get('a')); // 1
复制代码

Map作为参数
  1. let map2 = new Map([['text','世界现代设计史'],['name','王受之']])
  2. let m2 = new Map(map2)
  3. console.log(m2); // {'text' => '世界现代设计史', 'name' => '王受之'}
  4. console.log(m2.get('text')); // 世界现代设计史
  5. console.log(m2.get('hello')); // 读取不存在的键会返回undefined
复制代码

Map只有对同一个对象的引用才视为同一个键
  1. let map3 = new Map()
  2. map3.set(['a',100])
  3. console.log(map3.get(['a'])); // undefined
复制代码
因为数组不是引用类型,生成多个数组,它们的内存地址是不一样的,其实就是基础数据类型和引用数据类型的应用,这里的两个['a']看似是一样的,其实它们根本就是两个不同的值,Map只有对同一个对象的引用才视为同一个键,没有读取到所以返回undefined。请看下面的例子
  1. let map4 = new Map()
  2. let b = ['b']
  3. let b2 = ['b']
  4. map4.set(b)
  5. console.log(map4.get(b2)); // undefined
复制代码
Map的值其实是跟内存地址绑定的,内存地址不同,那么键就不同(即使名字一模一样),在这里Map就解决了同名属性冲突的问题,当我们使用别人的库时,使用对象名当做键,就不同担心自己的属性与别人的属性相同了。
如果Map的键是一个简单数据类型的值,如:number、string、boolean,只要这两个值严格相等,Map就视为同一个键,例如:0和-0就是同一个键,而布尔值true和字符串true就是不同的键,此外null和undefined也是不同的键。NaN视为同一个键。
  1. let n = new Map()
  2. n.set(0,100)
  3. console.log(n.get(-0)); // 100
  4. n.set(5,123)
  5. console.log(n.get('5'));  // undefined
  6. n.set(true,100)
  7. console.log(n.get(1)); // undefined
  8. n.set(NaN,123)
  9. console.log(n.get(NaN)); // 123
  10. n.set(null,100)
  11. console.log(n.get(null)); // 100
  12. console.log(n.get(undefined)); // undefined
复制代码
Map遍历方法

Map提供三个遍历器生成函数和一个遍历方法
方法说明Map.prototype.keys()返回键名的遍历器。Map.prototype.values()返回键值的遍历器。Map.prototype.entries()返回所有成员的遍历器。Map.prototype.forEach()遍历 Map 的所有成员。定义数据
  1. let m3 = new Map([
  2.        ['a',100],
  3.        ['b',200],
  4.        ['c',300]
  5. ])
复制代码
keys
  1. /* keys */
  2. for(let k of m3.keys()){
  3.    console.log(k);  // a  b  c
  4. }
复制代码
values
  1. /* values */
  2. for(let k of m3.values()){
  3.    console.log(k); // 100  200  300
  4. }
复制代码
entries
  1. for(let k of m3.entries()){
  2.     console.log(k); // ['a', 100]  ['b', 200]  ['c', 300]
  3.     console.log(k[0],k[1]); // a 100     b 200    c 300
  4. }
  5. // 或
  6. for(let [k,v] of m3.entries()){
  7.    console.log(k,v); // a 100     b 200    c 300
  8. }
复制代码
forEach
  1. m3.forEach(el => console.log(el))  // 100  200  300
  2. m3.forEach((val,index) => console.log(val,index))  // 100 'a'   200 'b'   300 'c'
复制代码
Map数据结构转换

Map转数组

使用扩展运算符将Map结构转换为数组
  1. let a = new Map([
  2.       ['a',1],
  3.       ['b',2],
  4.       ['c',3]
  5. ])
  6. console.log([...a.keys()]);  // ['a','b','c']
  7. console.log([...a.values()]); // [1,2,3]
  8. console.log([...a.entries()]); // ['a', 1]  ['b', 2]  ['c', 3]
  9. console.log([...a]); // ['a', 1]  ['b', 2]  ['c', 3]
复制代码
转换后的数组是一个真正的数组,可以使用数组方法
  1. let back = [...a].filter((val,index) => val[1] == 2 )
  2. console.log(back); // ['b',2]
复制代码
数组转Map
  1. let a2 = new Map([
  2.        ['name','东方不败'],
  3.        [{num : 3},['abc']]
  4. ])
  5. console.log(a2); // 0: {"name" => "东方不败"}    1: {Object => Array(1)}
复制代码


Map转对象
  1. let a3 = new Map()
  2. .set('a',100)
  3. .set('b',200)
  4. /* 通过函数传入map */
  5. function mapToObj(mapVal){
  6. // 在内部创建一个空对象
  7. let obj = {}
  8. // 遍历map结构,给空对象赋值
  9. for([k,v] of mapVal){
  10.       obj[k] = v
  11.   }
  12.     return obj
  13. }
  14. let mObj = mapToObj(a3)
  15. console.log(mObj); // {a: 100, b: 200}
复制代码

如果有非字符串键名,会被转换成字符串再创建对象键名

对象转Map
  1.        let obj = {'a':123,'b':456}
  2.        let mObj2 = new Map(Object.entries(obj))
  3.        console.log(mObj2);  // {'a' => 123, 'b' => 456}
复制代码


Map转JSON

Map转JSON需要区分两种情况
1、Map键名都是字符串
2、Map键名有非字符串的情况
1、Map键名都是字符串
可以写一个通用函数,用来将Map转为JSON
  1. let j = new Map()
  2. .set('name','东方')
  3. .set('text','不败')
  4. // mapToObj为上面创建的Map转对象的函数
  5. let shiftStrJson = (mapVal) => JSON.stringify(mapToObj(mapVal))
  6. console.log(shiftStrJson(j)); // '{"name":"东方","text":"不败"}'
复制代码
2、Map键名有非字符串的情况
  1. function shiftMaptoArrayJson(mapVal){
  2.      return JSON.stringify([...mapVal])
  3. }
  4. let j2 = new Map()
  5. .set('name','东方')
  6. .set('text','不败')
  7. let shiftStrJson2 = shiftMaptoArrayJson(j2)
  8. console.log(shiftStrJson2);  // '[["name","东方"],["text","不败"]]'
复制代码
以上两种的转换结果:


JSON转Map

JSON转Map需要区分两种情况
1、Map键名都是字符串
2、Map键名有非字符串的情况
1、键名都是字符串
  1. let strObj = '{"name":"东方","text":"不败"}'
  2. let strMap = new Map(Object.entries(JSON.parse(strObj)))
  3. console.log(strMap); // {'name' => '东方', 'text' => '不败'}
复制代码
2、键名有非字符串情况
  1. let strObj2 = '[["name","东方"],["text","不败"]]'
  2. let strMap2 = new Map(JSON.parse(strObj2))
  3. console.log(strMap2); // {'name' => '东方', 'text' => '不败'}
复制代码
案例源码:https://gitee.com/wang_fan_w/es6-science-institute
如果觉得这篇文章对你有帮助,欢迎点亮一下star哟

来源:https://www.cnblogs.com/wang-fan-w/p/17142937.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具