选择 JavaScript Map 而不是 Object 来存储键值对的 5 个理由(附示例)
18岁时,我开始了我的“职业生涯”,做IT支持人员。20
岁时,我成为了一名空乘人员,每月飞行80小时。22
岁时,我拿到了商用飞机飞行员执照。29
岁时,我是一名木匠,而如今32岁的我,是一名软件开发人员。
如果说我有什么擅长的,那就是跟上时代的步伐。因为如果你跟不上,就会被时代抛弃。我深知,使用自己熟记于心的东西比尝试“新事物”要舒服得多。
但不适感能让你成长,无论作为一个人还是一个开发者。
让我们一头扎进去,看看这些“新事物”Map今天能给我们带来什么启示。
Map 对象是什么?
以下是权威来源(MDN)的定义:
Map 对象存储键值对,并记住键的原始插入顺序。任何值(包括对象和基本类型值)都可以用作键或值。
简单来说,Map 是 JavaScript 的原生哈希或字典数据结构。
语法:Map 与 Object
这里有一张方便的速查表,很好地展示了它们的语法差异,这是Andrej在 Twitter 上发布的。
他还录制了性能测试视频,如果你感兴趣的话。
原因一:您不会意外覆盖默认密钥。
默认情况下, Map
对象不包含任何键。它是一个空白的画布,只包含你放入其中的内容。
不多不少,恰到好处。
对象
默认具有其原型,因此它包含默认键,这些默认键可能会与您自己的键冲突。
null可以通过在创建新对象时将原型传递来绕过此问题:Object.create(null)
看看区别:
- 新对象
null带有原型的新对象
原因二:它接受任何类型的键
Map
接受任何类型的键。这包括函数、对象和所有基本类型(字符串、数字、布尔值、符号、undefined、null 和 bigint)。
let obj = { 'a': 'a' };
let func = () => 'hey';
//you can also initialize multiple values at once using array syntax
let map = new Map([[123, true], [true, 123], [obj, 'object'], [func, 'function']])
map.keys() // 123, true, Object, () => 'hey'
map.get(obj) // 'object'
map.get(func) // 'function'
map.get({ 'a': 'a' }) // undefined
//Object and Functions are stored by reference, so { 'a':'a' } and obj are different objects)
对象
对象的键必须是字符串或符号。
let obj1 = { 'a': 'a' };
let func = () => 'hey';
let obj = { 123: true, true: 123, obj1: 'object', func: 'function' };
Object.keys(obj)
// ['123', 'true', 'obj1', 'func'] converts all keys to strings
obj[func] //undefined
obj['func'] // 'function'
原因三:地图是可迭代的
Map
本身是可迭代的。这意味着你可以使用循环遍历for of它们.forEach()。
const map = new Map();
map.set(0, 'zero').set(1, 'one'); //you can chain .set()
for (const [key, value] of map) {
console.log(`key: ${key}, value: ${value}`);
}
// key: 0, value: zero
// key: 1, value: one
//if you just want the 'values' or just the 'keys'
for (const key of map.keys()) { // or map.values()
console.log(key);
}
// 0
// 1
map.forEach((value, key) => console.log(`key: ${key}, value: ${value}`));
// key: 0, value: zero
// key: 1, value: one
对象
本身是不可迭代的,即使你可以使用for in`and`来遍历它们。Object.Entries()
let obj = { 0: 'zero', 1: 'one' }
for(let key in obj){
console.log(`key: ${key}, value: ${obj[key]}`)
}
// key: 0, value: zero
// key: 1, value: one
Object.entries(obj).forEach((item) => console.log(`key: ${item[0]}, value: ${item[1]}`))
// key: 0, value: zero
// key: 1, value: one
原因四:映射可以与数组合并,也可以转换为数组。
Map
和 Array 完全兼容,因此可以轻松地在两者之间进行转换。
以下是如何将 a 转换Map为 an 的方法Array
let map = new Map([ [1, 'one'], [2, 'two'] ]);
Array.from(map) //[ [1, 'one'], [2, 'two'] ] exactly the same array you initially passed in
//or you can use the spread operator
const newArr = [...map];
进入Array一个Map
let arr = [ [1, 'one'], [2, 'two'] ];
new Map(arr); //{ 1 => 'one', 2 => 'two' }
以下是如何合并aMap和 an 的方法Array
let map = new Map([ [1, 'one'], [2, 'two'] ]);
let arr = [3, 'three']
let combinedMap = new Map(...map, arr);
// { 1 => 'one', 2 => 'two', 3 => 'three' }
let combinedArr = [...map, arr];
// [ [1, 'one'], [2, 'two'], [3, 'three'] ]
对象
协调成Object一个Array
let obj = { 1: 'one', 2: 'two'};
Array.from(obj) // [] doesn't work
//you'd have to do
Array.from(Object.entries(obj))
//[ ['1', 'one'],['2', 'two'] ]
//or
[...Object.entries(obj)]
//[ ['1', 'one'],['2', 'two'] ]
原因五:您可以轻松查看尺寸
Map
有一个内置size属性可以返回其大小。
let map = new Map([1, 'one'], [true, 'true']);
map.size // 2
要检查对象
的大小,您需要结合Object.keys()使用.length
let obj = { 1: 'one', true: 'true' };
Object.keys(obj).length // 2
缺点?没有用于序列化和解析的本地方法。
Map
本身不支持与 JSON 进行序列化或解析。
文档建议通过使用replacer可以传递给JSON.stringify(obj, replacer)和reviver传递给的参数来实现自己的功能。JSON.parse(string, reviver)
您可以在这里找到建议的实现方案。
对象您可以使用相应的方法
将对象原生序列化和解析为 JSON,反之亦然。JSON.stringify()JSON.parse()
2 个可以Object用以下方式替换的例子Map
#1计算电子商务购物车的总价和商品数量
这是《JavaScript 完全指南》中 .reduce() 函数的示例之一。
给定以下数组
const shoppintCart = [
{ price: 10, amount: 1 },
{ price: 15, amount: 3 },
{ price: 20, amount: 2 },
]
我们想要返回一个Object类似这样的结果:{ totalItems: 6, totalPrice: 45 }
这是原始代码
shoppintCart.reduce(
(accumulator, currentItem) => {
return {
totalItems: accumulator.totalItems + currentItem.amount,
totalPrice:
accumulator.totalPrice + currentItem.amount * currentItem.price,
}
},
{ totalItems: 0, totalPrice: 0 } //initial value object
)
// { totalItems: 6, totalPrice: 45 }
这是使用以下版本的Map
shoppintCart.reduce(
(accumulator, currentItem) => {
accumulator.set('totalItems', accumulator.get('totalItems') + currentItem.amount);
accumulator.set('totalPrice', accumulator.get('totalPrice') + currentItem.price);
return accumulator;
},
new Map([['totalItems', 0], ['totalPrice', 0]])
)
// { 'totalItems' => 6, 'totalPrice' => 45 }
#2从数组中删除重复对象的另一种方法
这是我刚开始学习 JavaScript 时,在自己开发的图书架应用中使用的一段代码。
我在谷歌上搜索如何从数组中删除重复对象,找到了下面我分享的示例。
这是一个包含重复对象的数组
const books = [
{ id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie' },
{ id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie' },
{ id: 2, title: 'The Alchemist', author: 'Paulo Coelho' },
]
这里有一种奇特的删除重复项的方法:
const uniqueObjsArr = [
...new Map(books.map(book => [book.id, book])).values()
];
上面这短短一句话信息量有点大。
我们把它拆分成几个部分,以便更容易理解。
// 1. map the array into an array of arrays with `id` and `book`
const arrayOfArrays = books.map(book => [ book.id, book ])
// arrayOfArrays:
/*
[
[ 1, {id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie' } ],
[ 1, {id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie' } ],
[ 2, { title: 'Alchemist', author: 'Paulo Coelho' } ]
]
*/
// 2. The duplicate is automatically removed as keys have to be unique
const mapOfUniqueObjects = new Map(arrayOfArrays)
// mapOfUniqueObjects:
/*
{
1 => {id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie'},
2 => { title: 'Alchemist', author: 'Paulo Coelho' }
}
*/
// 3. Convert the values back into an array.
const finalResult = [...mapOfUniqueObjects.values()];
// finalResult:
/*
[
{id: 1, title: 'How To Win Friends And Influence People', author: 'Dale Carnegie'},
{id: 2, title: 'The Alchemist', author: 'Paulo Coelho'}
]
*/
结论
如果需要存储键值对(哈希或字典),请使用Map。
如果你只使用基于字符串的键,并且需要最高的读取性能,那么对象可能是更好的选择。
除此之外,你想用什么都行,因为说到底,这只是一个普通网友在网上写的一篇博客文章而已,哈哈。
以下是我们报道的内容:
- Map 对象是什么?
- 语法:Map 与 Object
- 原因一:您不会意外覆盖默认密钥。
- 原因二:它接受任何类型的键
- 原因三:地图是可迭代的
- 原因四:映射可以与数组合并,也可以转换为数组。
- 原因五:您可以轻松查看尺寸
- 缺点?没有用于序列化和解析的本地方法。
- 2 个可以
Object用以下方式替换的例子Map
感谢阅读!
如果您喜欢这篇文章:
*请在下方留言(打个招呼也行!)
*在推特上关注我@theguspear
回头见,
格斯。
文章来源:https://dev.to/gustavupp/5-reasons-to-choose-javascript-maps-over-objects-for-storing-key-value-pairswith-examples-39dd



