一篇文章搞懂Array,Set和Map异同
Last updated on June 17, 2025 pm
Array,Set和Map三个作为Javascript中可迭代的集合数据类型,在编程过程中使用的频率也比较高。针对三种数据类型各自的一些特性,本文的内容将从以下几个方面来上述数据类型做一个总结。
实例的创建
Map和Set创建实例的方式是唯一的,只允许通过new调用构造方法来创建一个实例。值得注意的是,Set和Map在调用构造函数的时候,传参都是数组或者可迭代对象,其中Map的传参数组需要时一个键值对数组。当然,传参也是可选的,非必须。
Array相较于前两者,其创建实例的方式要多写,可通过字面方式创建,也可像Map和Set一样通过构造函数来创建。此外使用Array的静态函数Array.from来创建也是非常常见的。例如,通过docuemnt.getElementsByTagName这类方法获取到一个HTMLCollect这样一个类数组,通常会通过Array.from将其装换成一个真正的数组来进行后续的操作。
1 |
|
数据添加与变更
1 |
|
数据访问
Array和Map都能够访问实例中的特定数据,Array是通过下标,而Map是通过实例方法get, 唯独Set没有方式可以直接访问其中特定数据。其实也不难理解,Set本身不是为了单纯存储数据和访问特殊而生的,因为这些功能Array就可以支持,何必再单出构造一个Set数据结构了。我对此的理解是,Set跟多的是紧紧围绕着数据唯一不重复这一准则来的,它的侧重点是某一数据的有无,而不是数据存在哪里。
另外,从结构上来说。Set不像Array那样是有序的,所以也无法使用下标来访问,也不像Map那般,每个键对应一个值,所以也无法通过键来访问。故而,Set没有单独访问某一数据的方式。
1 |
|
数据的遍历
Set数据的遍历方式:
- keys() 返回键名迭代器
- values() 返回值迭代器
- entries() 返回键值迭代器
- forEach()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21const set = new Set(['a', 'b', 'c']);
// set每个值对应的key其实也是数据值本身
const keyIter = set.keys();
console.log(keyIter.next().value); // 'a'
console.log(keyIter.next().value); // 'b'
console.log(keyIter.next().value); // 'c'
console.log(keyIter.next().value); // undefined
const valueIter = set.values();
for(let val of valueIter) {
console.log(val); // 'a', 'b', 'c'
}
const entriesIter = set.entries();
for(let [key, value] of entriesIter) {
console(`${key}:${value}`) // 'a':'a', 'b':'b', 'c':'c'
}
set.forEach(val => {
console.log(val) // 'a', 'b', 'c'
})
Map数据的遍历方式
- keys() 返回键名迭代器
- values() 返回值迭代器
- entries() 返回键值迭代器
- forEach()
1 |
|
Array数据的遍历方式
Array遍历数据的方法是最多的,除了下面列举的几个之外,还有some, every,甚至filter, find和findIndex这些方法可以用来遍历数据。使用这些方法需要注意的是其使用的场景,例如map和forEach都可以用来对数组内数据做一些操作,但如果不需要返回值的情况,还是使用forEach方法,而不建议是map,其它方法也是如此。
- keys() 返回键名迭代器
- values() 返回值迭代器
- entries() 返回键值迭代器
- map() 回调函数,要有返回值
- reduce()
- forEach()
- for…of
1
2
3
4/**
* 代码就不写了,偷个懒,不过还是贴心的附上链接
* https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array
**/
类似的功能和一些专有方法
- 是否包含某个元素: 数组的includes方法,map和set的has方法,三者的返回值都是布尔值,区别只在于传入的参数。数组和set传入的是值,map传入的是键。
- 合并两个相同类型的数据: 数组使用concat方法,合并两个数组值,set使用union方法合并两个集合。map没有专有方法可以用来合并两个map数据,不过可以通过使用new Map([…map1, …map2])来返回一个合并之后的新map
- 数据大小:数组有length属性,map和set有size属性
- 清空数据:map和size都可通过clear()方法来清空数据,数组无专有方法,可自己通过修改length值为0或者使用splice方法清空数据。
关于数组中的includes方法在数组值为一个个对象的时候,这个时候传入的值就只能是对象的引用了。如果作用域内不存在引用的话,判断数组中是否存在某个对象,就只能通过filter, find或者findIndex之类的方法加上数据特征去判断数组中是否存在该对象了。
三者之间的转换
1 |
|
应用场景
最常见的一种场景莫过于使用数组与Set之间格式变化进行数据去重1 |
|
上述方法和之前includes方法也是一样存在无法处理复杂数据类型,对于复杂对象数据,需要根据各自业务场景对重复的数据进行去重策略选择,即在一堆的重复对象中(以id重复为例)保留业务需要的唯一一个数据。
总结
三种数据结构有着各自不同的特性。数组是一个天然的栈,也是一个天然的队列,在三种数据结构中,其实例方法也应用也是最多的,是线性存储中话事人般的存在,也是我们在普通业务场景下的首选。Set数据的唯一性,可以帮助我们在业务场景中快速的进行去重。Map键值对结构的特殊性,以及对键的包容性,能够通过键快速获取到值,也是复杂业务冲常常用的。
【资料参考】