2.如何将JavaScript的Collection与Map一起使用

163 阅读6分钟

与许多其他编程语言不同,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,可以尝试一下,它可能会对您的开发工作带来很大的帮助。