0

悟透前端 | ECMAScript 6 的 Map 映射

 3 years ago
source link: https://xie.infoq.cn/article/b12c6d6700992222617fb2e30
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

映射(Map)是 ECMAScript 6 规范中引入的一种数据结构。这是一种存储键值对列表很方便的方法,类似于其他编程语言中的词典或者哈希表。



什么是映射



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



下面来看一个简单的示例,了解Map的基本用法:


//声明map实例
const page_info = new Map()
// 向 map 中添加元素
page_info.set("seo", {
"keywords": "infoq、Map",
"description":"Map对象是一种简单的键/值映射,其中的键和值可以是任意值(原始值或对象的值)"
})
page_info.set("title", "javascript es6的map映射")
console.log(page_info)
console.log(typeof page_info) // object


输出结果为:


Map {
'seo' => {
keywords: 'infoq、Map',
description: 'Map对象是一种简单的键/值映射,其中的键和值可以是任意值(原始值或对象的值)'
},
'title' => 'javascript es6的map映射'
}
object


从输出结果看,本质上Map(映射)就是一个 object 对象。



Object Map 区别

Object Map 的相似之处在于,都是按键存取一个值,而且键都是可以删除的。可以看出,二者之间是非常相似的,它的不同这之处在于:



 MapObject意外的键 Map  默认情况不包含任何键。只包含显式插入的键。

一个  Object  有一个原型, 原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。

注意:  虽然 ES5 开始可以用  Object.create(null)  来创建一个没有原型的对象,但是这种用法不太常见。

键的类型一个  Map 的键可以是 任意值 ,包括函数、对象或任意基本类型。一个 Object  的键必须是一个  String  或是 Symbol 。键的顺序 Map  中的 key 是有序的。因此,当迭代的时候,一个  Map  对象以插入的顺序返回键值。

一个  Object  的键是无序的

注意:自ECMAScript 2015规范以来,对象 确实 保留了字符串和 Symbol 键的创建顺序; 因此,在只有字符串键的对象上进行迭代将按插入顺序产生键。

size  Map  的键值对个数可以轻易地通过 size  属性获取 Object  的键值对个数只能手动计算迭代 Map  是 iterable 的,所以可以直接被迭代。迭代一个 Object 需要以某种方式获取它的键然后才能迭代。性能在频繁增删键值对的场景下表现更好。在频繁添加和删除键值对的场景下未作出优化。



Map映射常用方法



常用的 Map 方法有:赋值 set(key, value)  、获取 get(key)  、移除指定键名及其对应的值delete(key) 、判断是否存在 has(key)  、 获取所有值 values()  、 key/value 迭代器 entries() 、遍历 forEach() 和 清空所有键/值对 clear()   等。



声明并初始化

const new_map = new Map();
console.log(new_map); //输出:Map {}


赋值 set

赋值使用 map.set(key,value) ,可以用于增加新的 键/值 对或者修改 键/值 对,返回整个Map对象。


const page_info = new Map()
// 设置值
page_info.set("seo", {
"keywords": "infoq、Map",
"description":"Map对象是一种简单的键/值映射,其中的键和值可以是任意值(原始值或对象的值)"
});
console.log(page_info);
page_info.set("seo", "seo信息");
console.log(page_info);


上面的示例增加值,并修改值。


Map {
'seo' => {
keywords: 'infoq、Map',
description: 'Map对象是一种简单的键/值映射,其中的键和值可以是任意值(原始值或对象的值)'
}
}
Map { 'seo' => 'seo信息' }


获取键值 get

使用  get(key)  获取键值,如果获取的  key->value  不存则返回  undefined


const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
const title = page_info.get("title");
const seo_info = page_info.get("seo");
console.log(title); //javascript es6的map映射
console.log(seo_info); //undefined


删除键值 delete

map.delete(key)  删除指定  key  的键值对,返回成功或失败结果,删除成功返回 true ,删除失败返回 false


const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
page_info.set("author", "infoq");
console.log(page_info); // Map { 'title' => 'javascript es6的map映射', 'author' => 'infoq' }

const deleted_author = page_info.delete("author");
const deleted_seo = page_info.delete("seo");
console.log(deleted_author); // true
console.log(deleted_seo); // false
console.log(page_info); // Map { 'title' => 'javascript es6的map映射' }


判断键值是否存在 has

使用 map.has(key) 判断指定 key 是否存在。


const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
console.log(page_info); // Map { 'title' => 'javascript es6的map映射' }

console.log(page_info.has("title")); // true
console.log(page_info.has("seo")); // false


获取所有键值 values()

const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
page_info.set("author", "infoq");
console.log(page_info.values()); // [Map Iterator] { 'javascript es6的map映射', 'infoq' }


key/value 迭代器 entries()

使用 map.entries() 返回一个包含Map对象中每一个 [key, value] 数组的Iterator迭代器。


const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
page_info.set("author", "infoq");
console.log(page_info.entries());


输出的结果为:


[Map Entries] {
[ 'title', 'javascript es6的map映射' ],
[ 'author', 'infoq' ]
}


遍历所有键值 forEach(callback)

const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
page_info.set("author", "infoq");
page_info.forEach((value,key)=>{
console.log(key,value);
});


输出的结果为:


title javascript es6的map映射
author infoq


清空Map映射所有键值 clear()

使用 map.clear() 清空Map所有的键值对。


const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
page_info.set("author", "infoq");
page_info.clear();
console.log(page_info); // Map {}


与其它数据结构的转换



Map映射转为数组

Map转为数组最方便方法是使用扩展运算符 ...


const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
page_info.set("author", "infoq");
console.log([...page_info]); // [ [ 'title', 'javascript es6的map映射' ], [ 'author', 'infoq' ] ]


Map映射转为对象

function mapToObj(map) {
const obj = Object.create(null);
map.forEach((v,k)=>{
obj[k] = v;
});
return obj;
}
const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
page_info.set("author", "infoq");

console.log( mapToObj(page_info));


输出结果为:


[Object: null prototype] {
title: 'javascript es6的map映射',
author: 'infoq'
}


数组转为Map映射

将数组传入Map构造函数即可,即 new Map(array)


const page_info = [
["title","javascript es6的map映射"],
["author","infoq"]
];
console.log(new Map(page_info)); // Map { 'title' => 'javascript es6的map映射', 'author' => 'infoq' }


对象转为Map

对象转为Map映射通过 Object.entries()


const page_info = {
title:"javascript es6的map映射",
author:"infoq"
};
console.log(new Map(Object.entries(page_info))); // Map { 'title' => 'javascript es6的map映射', 'author' => 'infoq' }


映射Map转为JSON

Map 转为 JSON ,步骤是先把Map转为对象,即前面的 mapToObj ,然后使用 JSON.stringify 方法


function mapToObj(map) {
const obj = Object.create(null);
map.forEach((v,k)=>{
obj[k] = v;
});
return obj;
}
function mapToJson(map){
return JSON.stringify(mapToObj(map));
}
const page_info = new Map();
page_info.set("title", "javascript es6的map映射");
page_info.set("author", "infoq");
console.log( mapToJson(page_info)); // {"title":"javascript es6的map映射","author":"infoq"}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK