与许多其他编程语言不同,JavaScript处理数据采集的方式主要是使用对象和数组(别忘了,从技术上讲,数组也是JavaScript中的一种对象)。大多数开发人员严重依赖这些来将数据切片和切割成合适的数据结构。
在前ES6时代,处理数据采集的选项并不多。使用数组是实现它的好方法。数组和对象的结合使数据采集变得有用。但是,这也有一些缺点:
- Object的键只能是string类型。
- 对象没有一些重要的属性,比如知道它的大小,或者迭代它的灵活性。
- Object不维护其中元素的顺序。
ES6(ECMAScript 2015)为我们带来了两种新的数据结构Map和Set,使数据采集更加灵活和有用。在本文中,我们将回顾Map数据结构,以了解如何在实践中使用它。
Maps
Map是键值对的集合,其中键可以是任何类型。Map会记住元素的原始插入顺序。这意味着Map中的数据将按照插入顺序检索。
如果您仔细观察,Map具有Object和Array的特征。
- 对象特性-支持键值对结构。
- 数组特性-记住插入顺序
创建和初始化Map
可以创建一个新的map
const map = new Map();
它返回一个空的Map
Map(0) {}
这里需要注意的一点。新创建的Map没有默认键。然而,如果您创建一个JavaScript对象以使其像Map一样工作,它将从其原型继承属性。
创建Map的另一种方法是使用初始值。这里我们正在创建一个使用三个键值对初始化的Map
const greenrootsBlog = new Map([ ['name', 'greenroots'],
['type', 'blog'],
['writer', 'Tapas Adhikary'],
]);
它返回一个包含三个元素的Map
Map(3)
{
"name" => "greenroots",
"type" => "blog",
"writer" => "Tapas Adhikary"
}
向Map添加值
要为Map添加值,请使用set(key, value)方法。set(key, value)方法采用两个参数,key和value,其中键和值可以是任何类型、数据类型(boolean、string、number等)或对象。
const map = new Map(); map.set('name', 'greenroots');
map.set('type', 'blog');
map.set('writer', 'Tapas Adhikary');
输出
Map(3)
{
"name" => "greenroots",
"type" => "blog",
"writer" => "Tapas Adhikary"
}
请注意,如果您使用相同的键多次向Map添加值,它将始终替换最后一个值
map.set('writer', 'Someone else!');
现在map输出将是
Map(3)
{
"name" => "greenroots",
"type" => "blog",
"writer" => "Someone else!"
}
从map获取值
你现在一定已经猜到了。是的,Map有一个名为get(key)的方法,用于通过传递键(key)从中获取值。
map.get('name');
map.get('type');
map.get('writer');
请注意,如果将不存在的密钥传递给get(key)方法,则get(key)方法返回undefined。
Map Keys
对象和Map的一个突出区别是,Map的键可以是任何类型。让我们通过示例来看看。
const funMap = new Map();
funMap.set(360, 'My House Number');
funMap.set(true, 'I write blogs!');
let obj = {'name': 'tapas'}
funMap.set(obj, true); console.log(funMap);
输出
Map(3)
{
360 => "My House Number",
true => "I write blogs!",
{…} => true
}
此刻
funMap.get(360);
funMap.get(obj);
funMap.get('360');
常规JavaScript对象始终将键视为字符串。即使您将它们作为其他原始类型或对象传递,它也会在内部将键转换为字符串。这里有一个例子来理解它,
const funObj = {};
funObj[360] = 'My House Number';
console.log(funObj[360] === funObj['360']);
Map属性和方法
Map具有内置的属性和方法,使其功能强大且使用灵活。让我们创建一个Map来解释它们。
const map = new Map();
map.set('John', 34);
map.set('Alex', 15);
map.set('Buddy', 37);
了解Map的元素数
使用Map的size属性了解其中有多少元素。
console.log('size of the map is', map.size);
它重新运行Map中的元素数。在这种情况下,它将是3。
请注意:就像数组的长度一样,size也是一个属性,而不是一个方法。
查找带有has()的元素
如果Map有一个带有key的元素,则方法has(key)返回true。
console.log(map.has('John'));
console.log(map.has('Tapas'));
我们可以使用delete(key)方法从映射中删除一个元素。
map.delete('Buddy');
使用clear()方法一次从Map中删除所有元素。
map.clear();
map.size
MapIterator- Keys(), values(), entries()
到目前为止,我们看到的所有方法(除了clear())都是逐个处理Map的键值。有三种有用的方法可以分别获取所有键、值和键值对。
这些方法返回一个MapIterator,这非常好,因为您可以直接在其上执行for-of或foreach循环。
首先,创建Map
const ageMap = new Map([ ['Jack', 20],
['Alan', 34],
['Bill', 10],
['Sam', 9]
]);
获取所有的键
console.log(ageMap.keys());
输出
MapIterator {"Jack", "Alan", "Bill", "Sam"}
获取所有值
console.log(ageMap.values());
输出
MapIterator {20, 34, 10, 9}
获取所有条目(键值对)
console.log(ageMap.entries());
输出
MapIterator {"Jack" => 20, "Alan" => 34, "Bill" => 10, "Sam" => 9}
遍历Map
有多种方法可以遍历Map。您可以使用foreach或for-of循环来遍历它。
使用forEach
ageMap.forEach((value, key) =>
{ console.log(`${key} is ${value} years old!`);
});
注意,第一个参数是值,第二个是键。输出是,
Jack is 20 years old!
Alan is 34 years old!
Bill is 10 years old!
Sam is 9 years old!
使用for-of
我们可以简单地使用for-of循环从Map中解构键和值。
for(const [key, value] of ageMap) {
console.log(`${key} is ${value} years old!`);
}
Object to Map
您可能会遇到需要将对象转换为类似Map的结构的情况。您可以使用Object的entries方法来执行此操作。
const address = {
'Tapas': 'Bangalore',
'James': 'Huston',
'Selva': 'Srilanka'
};
const addressMap = Object.entries(address);
Map to Object
如果你想做相反的事情,你可以使用名fromEntries的方法。
Object.fromEntries(map)
Map to Array
有几种方法可以将映射转换为数组。
-
使用Array.from(map)
const map = new Map(); map.set('milk', 200); map.set("tea", 300); map.set('coffee', 500); console.log(Array.from(map));输出
-
使用扩展运算符将Map转换为数组。
console.log([...map]);
Map vs Object:什么时候用什么?
Map具有对象和数组的特性。然而,由于以键值格式存储数据的性质,Map更像是一个对象而不是数组。
不过,与对象的相似性到此为止。正如我们目前所看到的,Map在许多其他方面与对象非常不同。那么,使用哪一个,什么时候?如何使用?
何时使用Map
- 您的需求并不简单。您可能希望创建非字符串的键。将对象存储为键是一种非常强大的方法。默认情况下,Map会提供给您。
- 您需要一个可以对元素进行排序的数据结构。对象不保持顺序。
- 您正在寻找灵活性,而不依赖于像lodash这样的外部库。您最终可能会使用像lodash这样的库,因为我们找不到像has()、values()、delete()这样的方法或对象的size属性。Map默认提供它们对您来说很容易。
何时使用对象
- 你没有像上面这样的任何需求
- 您依赖JSON.parse(),因为它无法解析Map。
结语
Map 是 JavaScript 中非常有用的一种数据结构,可以帮助我们更方便地存储和访问数据。如果您还没有使用过 Map,可以尝试一下,它可能会对您的开发工作带来很大的帮助。