关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

Map数据结构详解

发布时间:2023-06-29 22:00:41
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哟

/template/Home/leiyu/PC/Static