终于,我们要说到ES6中最强大的功能------图Map
图是JavaScript中一种全新的数据结构。在图中你可以载入不同的数据类型,并为他们分配对应的键值。通过图可以很方便的对内部进行详细的数据操作,一些在对象中比较复杂的操作方式在图Map
中会变得比较简单。
其次,相比于对象Object
,图Map
中的一个键只能出现一次,这样不仅可以减少不必要的关联,使得图数据处理具有更高的性能;在一定程度上也能降低因为键和值的滥用导致对象注入攻击,增强了数据结构的可靠性和安全性。
MDN官网上对于图Map的详细说明🔎:developer.mozilla.org/zh-CN/docs/...
创建一个图
和集合一样,你需要使用一个Map()
构造函数创建一个图。并用set
方法将键值keys
和对应的内容Content
传入到图内。
dart
const rest = new Map(); //Create a null map // rest.set(/* key */, /* value */);
rest.set('name', 'LeeLin'); //arr.add()
rest.set(1, 'ZhaoCheng');
console.log(rest.set(2, 'Sam kong'));

如果你觉得频繁使用set
方法很麻烦,图下的set
方法同样支持一下写法:
bash
rest
.set('categories', ['意大利', '比萨店', '素食', '有机'])
.set('open', 11)
.set('close', 23)
.set(true, 'We are open😀')
.set(false, 'We are closed😴');
获取图Map中的内容
要想获取图中对应键值的内容,你需要使用Map下的get()
方法即可获取。
实际上这两个方法非常好记,设置键值和其对应的值与内容使用set()
方法,反过来获取键值对应的值和内容使用get()
即可。
dart
const rest = new Map(); //Create a null map // rest.set(/* key */, /* value */);
rest.set('name', 'LeeLin'); //arr.add()
rest.set(1, 'ZhaoCheng');
console.log(rest.set(2, 'Sam kong'));
rest
.set('categories', ['意大利', '比萨店', '素食', '有机'])
.set('open', 11)
.set('close', 23)
.set(true, 'We are open😀')
.set(false, 'We are closed😴');
console.log(rest.get('name'));
console.log(rest.get(true));
console.log(rest.get(1));

另外,Map图中的get()
使用方法非常灵活,例如下面我们可以直接在get()
方法内插入逻辑表达式来对变量time
进行判断。从得出的true
或false
映射到键值对应的内容,是'We are open😀'
还是'We are closed😴'
。
sql
const time = 8;
console.log('test: ',
rest.get(time > rest.get('open') && time < rest.get('close')));
//true -> We are open😀

判断图中是否有相关键值对应的元素
在集合中同样使用的has()
方法,在图Map
数据结构中同样适用。你依然可以使用has()
方法查找键值对应的内容。例如查询rest
图中是否存在'categories'
键值。

arduino
console.log(rest.has('categories'));
console.log(rest);

下面列出三个和集合数据结构中一样的方法------delete删除
、clear删除图中的全部内容
、size计算图的大小
。
删除图中的键值及其对应的元素
同样,在集合Set()
中可以使用的delete
方法,在Map
图中也同样可以使用。
scss
rest.delete(2);
console.log('Delete the key 2: ', rest);

清除图内容的所有元素
如有必要,你可以使用Map
图下的clear
方法清除图中的所有内容。注意此方法和集合Set()
中的使用方法一样.
scss
rest.clear(); // 图Map当然可以和集合一样,你也可以清空图中的内容
console.log('after clear the rest Map: ', rest);

计算图的大小
如果你想获取图中键对应的值占用图中多大空间------也就是图的大小是什么。你可以使用size()
方法获取图的大小。
arduino
console.log('OutPut the rest map size: ', rest.size); //7 //打印图的大小

关于图的键值
既然图中可以存放任何数据类型的变量和内容。实际上,图Map中的键值也可以有多种,甚至你可以将一个数组、一个HTML文本DOM对象定义为一个键值;并为他们映射到相关的内容上。
例如下面将数组arr
键值映射到字符串'test'
上。
c
const arr = [1, 2];
rest.set(arr, 'Test'); // To call the reflected the key
rest.set(document.querySelector('h1'), 'Heading'); // Even you can control the DOM Object in the map
console.log('rest: ', rest); // So we can use the object to call the value
console.log('rest.size: ', rest.size);

观察rest
图内内容,你会发现键值数组[1,2]
对应着字符串'Test'
内容,而文本节点HTML中的DOM:h1
对应的内容是字符串"Heading"
。通过这个例子可以充分反映出JavaScript中图数据结构的多样性,其数据组成的松散性可以为构造大型的JavaScript应用程序及其web网络应用提供相当大的便利。
JavaScript中图Map的高级操作
在图中想设置键值和键值下的内容,我们需要使用set()
方法来完成此操作。但如果我们要一次性的输入多个键值对应的内容,此时反复的使用set
方法就会变的非常麻烦。有没有一种方法可以一次性的输入多个键和对应的值。
当然有,ES6中的图操作系统了一种非常简单的方式进行此操作。
使用Map
构造函数一次性输入多个键和对应的值
css
const question = new Map([ ['question', 'What is the best programming language in the world?'],
[1, 'C'],
[2, 'Java'],
[3, 'JavaScript'],
['correct', 3],
[true, 'Correct✅'],
[false, 'Try again!'],
]);
console.log(question);
创建一个question
的图,我们可以使用构造函数Map
一次性将多个键和值传入question
图中。另外,图中的每个键对应的内容都是用数组的形式进行封装。这个与JavaScript中的对象有非常大的区别。

并且用构造函数方法创建的Map同样可以使用has()
、size()
、delete()
、clear()
等方法。并且也可以使用for-of
循环♻️对图Map进行操作。例如如果question
图下的key
键的类型是Number
的话,就打印出该键值和其对应的内容。
javascript
//Map 数据结构也是可迭代的🔁
console.log(question.get('question'));
for (const [key, value] of question) {
if (typeof key === 'number') console.log(`Answer ${key}: ${value}`);
}

将对象Object
转换成图Map
还记得对象和数组中的entries()
方法吗,通过这个方法可以自动生成数字索引
和对应的键值及其内容
。这种数据结构对比图,你会发现两者有着异曲同工之妙,下面用伪代码来体现两者的异同。
ini
/* 伪代码 */
console.log(Object.entries(obj));
/*
[Array(2),Array(2),Array(2)]
[
0: ['content', {objCotnent1}],
1: ['content', {objCotnent2}],
2: ['content', {objCotnent3}],
]
*/
const test = new Map(
['key','content'],
[1,'content'],
['key','content'],
)
console.log(test);
/*
Map{'key' => 'content', 1 => 'content', 'key' => 'content'}
Map{
0:{"key" => "content"}
1:{1 => "content"}
2:{"key" => "content"}
}
*/
实际上,在图中一切键值和元素已经被分配好了对应的索引号。因此这也解释了为什么图结构Map
也可以通过for-of
循环♻️进行便利。
javascript
// Convert object to map
console.log(Object.entries(openingHours));
const hoursMap = new Map(Object.entries(openingHours));
console.log(hoursMap);

将数组转换成图Map
同样使用ES6中的扩展语法可以...
轻而易举的解构图Map
中的内容,方便的将它们放置在数组中,形成一个数组结构。另外,图中的键和内容可以分开转换数组。(图中的键使用keys()
方法,图中的值使用values()
方法)。
ini
//Convert map to array
console.log([...question]);
console.log(question.entries());
console.log([...question.keys()]);
console.log([...question.values()]);


关于图的其他操作
当然,像对象、数组、集合可以做的逻辑布尔操作、拷贝复制操作一样可以完成。你一样可以在图的get()
方法中插入逻辑表达式进行分析和判断。例如下面这个例子中使用图下的get()
方法对其进行逻辑表达式操作。
判断哪个是最好的编程语言 ,接收用户输入的数字,并将此数字与question
图中对应的键进行比较。从而得出相应的结果。
ini
//Guess which is the best programming language
const answer = Number(prompt('Your answer'));
// const answer = 3;
console.log(answer);
const tag = question.get('correct') === answer;
// console.log(tag);
console.log(question.get(tag));

图Map
作为JavaScript ES6版本中的一个新的数据结构,其功能在某些方面(键和值的增删改查、获取大小、迭代🔁图内部的键和值)甚至可以替代对象Object
数据类型。但在深拷贝方面,例如使用JSON.parse()
下的JSON.Stringify()
方法进行深拷贝操作,来实际操作对象中的内容而不是对象的副本。这种情况推荐使用对象。因为这种操作目前在图Map
中仍比较麻烦。关于图Map
数据结构肯定不是这样短短一篇文章就可以阐述清楚的,我会继续在实践中运用图Map
结构,并进一步补充和完善这部分的内容。
未完持续...🎒