44

JavaScript 的 Map 指南[每日前端夜话0xC7]

 4 years ago
source link: https://www.tuicool.com/articles/fyiEreA
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.

每日前端夜话 0xC7

每日前端夜话,陪你聊前端。

每天晚上18:00准时推送。

正文共:3066 字

预计阅读时间:10 分钟

作者:Valeri Karpov

翻译:疯狂的技术宅

来源: thecodebarbarian

U32i227.png!web

在JavaScript中,Map 是存储键/值对的对象。Map 类似于一般 JavaScript 对象【 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object 】 ,但对象与 Map 之间一些关键的差异【 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map#Objects_and_maps_compared 】使 Map 很有用。

Map 与 Object

如果你要创建一个存储一些键/值路径的 JavaScript 对象,可以定义一个普通 JavaScript 对象(plain-old JavaScript object),其简称为“ POJO”,如下所示。

1const obj = {
2 name: 'Jean-Luc Picard',
3 age: 59,
4 rank: 'Captain'
5};
6
7obj.name; // 'Jean-Luc Picard'

你还可以定义一个包含如下所示的键和值的映射。

 1const map = new Map([
2 // 你可以通过二维数组定义 Map。 首先
3 // 每个嵌套数组的元素是键,第二个是值
4 ['name', 'Jean-Luc Picard'],
5 ['age', 59],
6 ['rank', 'Captain']
7]);
8
9// 要获得与 Map 中给定的“键”关联的值,你需要
10// 调用 map.get(key)`。 使用 map.key 将不起作用。
11map.get('name'); // 'Jean-Luc Picard'

假设你想获得 Picard 船长的 age 。对于一个对象,你可以用 obj.age 。对于 map,你要用 map.get('age') 。对于与内置 JavaScript 功能没有冲突的属性来说这很好用,但是如果你想获取对象的 constructor 属性【 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor 】会怎样呢?在这种情况下,只定义了 obj.constructor ,但未定义 map.get('constructor')

1obj.constructor; // [Function: Object]
2map.get('constructor'); // undefined

映射没有继承的任何概念:映射没有任何继承的键。这使 map 成为存储原始数据的理想选择,而不必担心数据与现有方法和属性发生冲突。例如,map 不受原型污染这个安全漏洞的影响,用户数据的简单复制可能会使恶意用户覆盖类方法。

另一个关键差异是,映射允许你存储对象键,而不仅仅是字符串。但是当你把日期或数字等对象存储为键时,可能会引起一些混乱。

 1const map = new Map([]);
2
3const n1 = new Number(5);
4const n2 = new Number(5);
5
6map.set(n1, 'One');
7map.set(n2, 'Two');
8
9// n1 和 n2 是对象,因此 n1!== n2。
10// 这意味着 map 具有分别用于 n1 和 n2 的键。
11map.get(n1); // 'One'
12map.get(n2); // 'Two'
13map.get(5); // undefined
14
15//如果要对一个对象执行此操作,则 n2 会覆盖 n1
16const obj = {};
17obj[n1] = 'One';
18obj[n2] = 'Two';
19
20obj[n1]; // 'Two'
21obj[5]; // 'Two'

Map 还具有 size 属性,该属性返回 map 中键/值对的数量。为了获得一个对象中键的数量,你必须要调用 Object.keys(obj).length

1map.size; // 3

另一个区别是,这保证了键在 map 中的顺序。换句话说,如果你调用 map.keys() ,你将 总是 按照将键添加到 map 的顺序获取键。在 Picard 船长的示例中, map.keys() 将始终按该顺序返回 name , agerank

这也能够保证符合ES6的浏览器的对象键顺序。例如在与 ES6 兼容的 JavaScript 运行时中, Object.keys(obj) 将始终返回 ['name', 'age', 'rank'] 。但是在较早的运行时(例如 Internet Explorer 等)中, Object.keys(obj) 可能会以不同的顺序返回键。

Map#keys(), Map#values(), Map#entries()

Map 具有3种内置的迭代方法: keys()values() )和 entries() 。与 Object.keys() 不同, Map#keys() 函数返回一个 iterator 而不是数组。这意味着迭代 map 键的最简单方法是使用 for/of 循环。

 1const map = new Map([
2 ['name', 'Jean-Luc Picard'],
3 ['age', 59],
4 ['rank', 'Captain']
5]);
6
7const iterator = map.keys();
8console.log(iterator); // MapIterator { 'name', 'age', 'rank' }
9
10// `map.keys()` returns an iterator, not an array, so you can't
11// access the values using `[]`
12iterator[0]; // undefined
13
14// The `for/of` loop can loop through iterators
15for (const key of map.keys()) {
16 key; // 'name', 'age', 'rank'
17}

有时将迭代器转换为数组很方便,因此你可以用 filter()map() 。将迭代器转换成数组的最简单方法是使用内置的 Array.from() 函数。

1const arr = Array.from(map.keys());
2
3arr.length; // 3
4arr[0]; // 'name'
5arr[1]; // 'age'
6arr[2]; // 'rank'

Map#entries() 函数还返回一个迭代器。迭代器遍历 map 的值:

1for (const v of map.values()) {
2 v; // 'Jean-Luc Picard', 59, 'Captain'
3}

最后, Map#entries() 返回一个迭代器,该迭代器以与 Map 构造函数类似的格式遍历 map 的键/值对。 Map#entries() 函数是 Map 类的等效项,它等效于 Object.entries

1for (const [key, value] of map.entries()) {
2 key; // 'name', 'age', 'rank'
3 value; // 'Jean-Luc Picard', 59, 'Captain'
4}

Map#entries() 函数使复制 map 变得很容易。克隆 map 就像将   Map.entries() 转换成数组一样简单:

1// `clone` is now a separate map that contains the same keys/values
2// as `map`.
3const clone = new Map(Array.from(map.entries));

扩展

尽管 JavaScript 开发人员通常用对象来存储数据,但是 map 具有一些优点:没有原型污染或 JSON 数据覆盖类方法的风险。如果要在不设置 symbol 的情况下将数据与对象相关联,映射还允许你存储对象键,这会很有用。Map 在开源 JavaScript 中仍然很少见,我唯一见过的重要用例子是 Mongoose's map type 。但是 map 值得去取代 JSON ,因为它避免了原型污染的风险。

原文: http://thecodebarbarian.com/the-80-20-guide-to-maps-in-javascript.html

下面夹杂一些私货:也许你和高薪之间只差这一张图

2019年京程一灯课程体系上新,这是我们第一次将全部课程列表对外开放。

愿你有个好前程,愿你月薪30K。我们是认真的 ! BbquyaF.png!web

zMFVruu.jpg!web

在公众号内回复“体系”查看高清大图

长按二维码,加大鹏老师微信好友

拉你加入前端技术交流群

唠一唠怎样才能拿高薪

JFNJFbv.jpg!web

小手一抖,资料全有。长按二维码关注 前端先锋 ,阅读更多技术文章和业界动态。

MFryQjN.gif


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK