ES6中的map集合

129 阅读3分钟

Map

Javascript的对象(Object),本质上是键值对的集合(Hash结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制,为了解决这个问题,ES6提供了Map数据结构,它类似于对象,也是键值对的集合,但是,键的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object结构提供了“字符串-值”的对应,Map结构提供了“值-值”的对应,是一种更完善的Hash结构实现。

创建Map

let map = new Map()
map.set('jack',18)
map.set('ross',20)
console.log(map) 

image.png

Map也可以接受数组作为参数。

let map = new Map([
  ['name','张三'],
  ['title','Author']
])
map.size
map.has('name')
map.get('name')
map.has('title')
map.get('title')

image.png

如果对同一个键多次赋值,后面的值会覆盖掉前面的值

let map = new Map();
map
.set(1,'aaa')
.set(1,'bbb')
map.get(1) // 'bbb'

实例的属性和操作方法

1、size属性:size属性返回map结构的成员总数

let map = new Map();
map.set('foo',true),
map.set('bar',false);
map.size //2

2、set(key,value) :set方法设置key所对应的键值,然后返回整个Map结构,如果key已经有值,则键值会被更新,否则就新成该键。

var m = new Map();
m.set("edition", 6)        // 键是字符串
m.set(262, "standard")     // 键是数值
m.set(undefined, "nah")    // 键是undefined

//set方法返回的是Map本身,可以采用链式写法  
let map = new Map()
  .set(1, 'a')
  .set(2, 'b')
  .set(3, 'c');

3、get(key):get方法获取key对应的键值,如果找不到key,返回undefined

var m = new Map();
var hello = function() {console.log("hello");}
m.set(hello, "Hello ES6!") // 键是函数
m.get(hello)  // Hello ES6!

4、has(key):has方法返回一个布尔值,表示某个键是否在Map数据结构中

let m = new Map()  
m.set('name','jack')
m.has('name') // true
m.has('age')  // false

5、delete(key): delete方法删除某个键,返回true,如果删除失败,返回false。

var m = new Map();
m.set(undefined, "nah");
m.has(undefined)     // true
m.delete(undefined)
m.has(undefined)       // false

6、clear(): clear方法清除所有成员,没有返回值。

let map = new Map();
map.set('foo', true);
map.set('bar', false);
map.size // 2
map.clear()
map.size // 0

遍历方法

keys(): 返回键名的遍历器
values(): 返回键值的遍历器
entries(): 返回所有成员的遍历器
forEach(): 遍历Map的所有成员

let map = new Map([
  ['F', 'no'],
  ['T',  'yes'],
]);

for (let key of map.keys()) {
  console.log(key);
}
// "F"
// "T"

for (let value of map.values()) {
  console.log(value);
}
// "no"
// "yes"

for (let item of map.entries()) {
  console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"

// 或者
for (let [key, value] of map.entries()) {
  console.log(key, value);
}

// 等同于使用map.entries()
for (let [key, value] of map) {
  console.log(key, value);
}

与其他数据结构相互转换

1、Map转数组: Map转为数组,可以使用扩展运算符(...)

let map = new Map().set(true,7).set({foo:3},['abc'])
console.log([...map]) //[[true,7],[{foo: 3}, ['abc']]]

2、数组转map:将数组传入构造函数,就可以转为Map

 let map = new Map([[true,7],[{foo: 3}, ['abc']]])
 console.log(map)  // {true => 7,{foo:3 } => ['abc']}

3、Map转对象:如果所有Map键都是字符串,它可以转为对象

function strMapToObj(strMap) {
  let obj = Object.create(null);
  for (let [k,v] of strMap) {
    obj[k] = v;
  }
  return obj;
}
let myMap = new Map().set('yes', true).set('no', false);
strMapToObj(myMap) // {yes: true, no: false}

4、对象转为Map

function objToStrMap(obj) {
  let strMap = new Map();
  for (let k of Object.keys(obj)) {
    strMap.set(k, obj[k]);
  }
  return strMap;
}
objToStrMap({yes: true, no: false}) 
//[ [ 'yes', true ], [ 'no', false ] ]

5、Map转JSON
Map转JSON分两种情况,一种是当Map的键都是字符串,这时可以选择转为对象JSON

function strMapToJson(strMap) {
  return JSON.stringify(strMapToObj(strMap));
}
let myMap = new Map().set('yes', true).set('no', false);
strMapToJson(myMap) // '{"yes":true,"no":false}'

另一种情况是,Map的键名有非字符串,这时可以选择转为数组JSON

function mapToArrayJson(map) {
  return JSON.stringify([...map]);
}

let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
mapToArrayJson(myMap) // '[[true,7],[{"foo":3},["abc"]]]'

6、JSON转Map
分两种情况,当所有键名都是字符串时:

function jsonToStrMap(jsonStr) {
  return objToStrMap(JSON.parse(jsonStr));
}
jsonToStrMap('{"yes":true,"no":false}') // {'yes' => true, 'no' => false}

另一种情况,当整个JSON是一个数组,且每个数组成员本身,又是一个有两个成员的数组,这时,它可以一一对应地转为Map,这往往是数组转JSON的逆操作

function jsonToMap(jsonStr) {
  return new Map(JSON.parse(jsonStr));
}

jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
//{true => 7, Object {foo: 3} => ['abc']}