2

ES6 给我们提供了 Map 数据结构,它类似于对象,用于保存键值对。不同的是,Map 中键的范围不限于字符串类型,各种类型的值(包括对象)都可以当作一个键或一个值。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果需要用到“键值对”的数据结构,MapObject 更合适。

Map和Object的区别

  • Object 中的键只能是字符串或者 Symbols 类型,但 Map 中的键可以是任意值。
  • Map 中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
  • Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
  • Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。

创建Map

MapES6 提供给我们的构造函数,本质上是键值对的集合。任何值(对象或者原始值) 都可以作为一个键或一个值。

示例:

我们可以通过 Map() 方法来创建一个空 Map

let map = new Map();
console.log(map);  // 输出:Map {}

上述代码中,我们可以在创建时初始化 Map 时,Map 可以接收数组作为参数,并且数组成员也是一个个数组,其中包含两个元素,一个表示键,一个表示值。

示例:

例如下面这个 Map 中有两个键值对:

let map = new Map([["name","xkd"],['age','18']]);
console.log(map);
// 输出:Map { 'name' => 'xkd', 'age' => '18' }

第一个键值对中键为 name,值为 xkd,第二个键值对中键为 age,值为 18

Map的方法和属性

set()方法

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

示例:
let map = new Map();
map.set('name', 'xkd');
console.log(map);  // 输出:Map { 'name' => 'xkd' }

如果要设置多个键值对,则可以执行多次 set 方法。

示例:

例如向 map 中添加三个键值对:

let map = new Map();
map.set('a', 1);
map.set('b', 2);
map.set('c', 3);
console.log(map);  
// 输出:Map { 'a' => 1, 'b' => 2, 'c' => 3 }

get()方法

get() 方法用于读取 key 对应的键值,如果找不到 key,则返回 undefined

示例:

下面代码中我们通过 set() 方法为 Map 设置键值对,然后通过 get() 方法获取指定键对应的值:

let map = new Map();
map.set('a', 1);
map.set('b', 2);
map.set('c', 3);

console.log(map.get('a'));  // 输出:1
console.log(map.get('b'));  // 输出:2
console.log(map.get('c'));  // 输出:3
console.log(map.get('d'));  // 输出:undefined

可以看到,如果我们想要取读取的键值在 map 中不存在,例如 d,那么最终会输出 undefined

has()方法

has() 方法返回一个布尔值,表示某个键是否在 Map 数据结构中。在则返回 true,不在则返回 false

示例:
let map = new Map();
map.set('a', 1);
map.set('b', 2);
map.set('c', 3);

console.log(map.has('a'));    // 输出:true
console.log(map.has('b'));    // 输出:true
console.log(map.has('name')); // 输出:false

上述代码中,我们先通过 set() 方法 向 map 中添加了三个键值对,但是很明显 ab 存在 map 数据结构中,而 name 不存在。

delete()方法

delete() 方法用于删除某个键,删除成功返回 true,如果删除失败则返回 false

示例:
let map = new Map();
map.set('a', 1);
map.set('b', 2);
map.set('c', 3);

console.log(map.delete("a"));    // 输出:true
console.log(map.delete("age"));  // 输出:false

可以看到,因为 amap 中的键,所以删除 a 时返回 true 值。而 age 不是 map 中的键,所以返回 false

clear()方法

clear() 方法用于清除 Map 中所有成员,没有返回值。

示例:

Map 中的成员很多是,如果使用 delete() 方法一个键一个键删除会很麻烦,所以如果要清除 Map 中所有的成员,可以直接使用 clear() 方法:

let map = new Map();
map.set('a', 1);
map.set('b', 2);
map.set('c', 3);

map.clear();
console.log(map);  // 输出:Map {}

size属性

size 属性可以用于返回 Map 中成员总数。

示例:
let map = new Map();
map.set('a', 1);
map.set('b', 2);
map.set('c', 3);

console.log(map.size);  // 输出:3

Map 遍历方法

Map 原生提供三个遍历器生成函数和一个遍历方法。

示例:

我们先创建并初始化一个 Map

let map1 = new Map([
    ["x", 1],
    ["k", 2],
    ["d", 3]
]);

keys()方法

keys() 方法是一个用于返回键名的遍历器。

示例:

例如通过 keys() 方法遍历 map1

for(let key of map1.keys()){
    console.log(key);
}

输出:

x
k
d

从上述输出中可以看出,成功遍历了 map1 中的所有键值。

values()方法

values() 方法与 keys() 对应,是一个用于返回键值的遍历器。

示例:

例如通过 values() 方法遍历 map1

for(let v of map1.values()){
    console.log(v);
}

输出:

1
2
3

entries()方法

如果我们又想要遍历 Map 中的键又想要遍历 Map 中的值,可以使用 entries() 方法,entries() 方法用于返回所有成员的遍历器。

示例:
let map1 = new Map([
    ["x", 1],
    ["k", 2],
    ["d", 3]
]);
for(let [key,value] of map1.entries()){
    console.log(key+':'+value);
}

输出:

x:1
k:2
d:3

forEach()方法

forEach() 方法用于遍历 Map 的所有成员,第二个参数绑定 this

示例:
map1.forEach(function(value, key){
    console.log(key+':'+value);
});

输出:

x:1
k:2
d:3

Map的类型转换

Map 类型可以与其他的数据类型进行转换,我们一起来看一下。

示例:
  • Map 转为数组类型:可以使用扩展运算符... 来实现。
let map1 = new Map();
map1.set("name", "xkd");
console.log([...map1]);  
// 输出:[ [ 'name', 'xkd' ] ]
  • 数组类型转为 Map :将数组传入 Map 构造函数即可。
let map1 = new Map([
    ["x", 1],
    ["k", 2],
    ["d", 3]
]);
  • Map 转为对象:如果所有 Map 的键都是字符串,它可以无损地转为对象。如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。
function strMapToObj(strMap) {
    let obj = Object.create(null);
    for (let [k,v] of strMap) {
      obj[k] = v;
    }
    return obj;
}
  
let map1 = new Map();
map1.set("name", "xkd");
console.log(strMapToObj(map1));  
// 输出:[Object: null prototype] { name: 'xkd' }
  • 对象转为 Map:可以使用 Object.entries() 方法来实现。
let obj = {"a":1, "b":2};
let map1 = new Map(Object.entries(obj));
console.log(map1); 
// 输出:Map { 'a' => 1, 'b' => 2 }
  • Map 转为 JSON:分为两种情况,一种是 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 map1 = new Map().set('a', 1).set('b', 2);
console.log(strMapToJson(map1)); // 输出:{"a":1,"b":2}

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

function mapToArrayJson(map) {
    return JSON.stringify([...map]);
}
  
let map1 = new Map().set(true, 1).set({b: 2}, 2);
console.log(mapToArrayJson(map1));  // 输出:[[true,1],[{"b":2},2]]
  • JSON 转为 Map:如果所有键名都是字符串则可以像下面这个。
function objToStrMap(obj) {
    let strMap = new Map();
    for (let k of Object.keys(obj)) {
      strMap.set(k, obj[k]);
    }
    return strMap;
}
function jsonToStrMap(jsonStr) {
    return objToStrMap(JSON.parse(jsonStr));
}
  
console.log(jsonToStrMap('{"a": 1, "b": 2}'));  
// 输出:Map { 'a' => 1, 'b' => 2 }

如果整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组。它可以一一对应地转为 Map。这往往是 Map 转为数组 JSON 的逆操作。

function jsonToMap(jsonStr) {
    return new Map(JSON.parse(jsonStr));
}
  
console.log(jsonToMap('[[1, 100],[{"age":18},[20]]]'));
// 输出:Map { 1 => 100, { age: 18 } => [ 20 ] }

链接:https://www.9xkd.com/


知否
221 声望177 粉丝

Skrike while the iron is hot.