前言
本文2895字,阅读大约需要12分钟。
总括: 本文总结了10种常见的数组去重方法,并将各种方法进行了对比。
- 公众号:「前端进阶学习」,回复「666」,获取一揽子前端技术书籍
如烟往事俱忘却,心底无私天地宽。
正文
数组去重对于前端来说不是一个常见的需求,一般后端都给做了,但这却是一个有意思的问题,而且经常出现在面试中来考察面试者对JS的掌握程度。本文从数据类型的角度去思考数组去重这个问题,首先解决的是数组中只有基础数据类型的情况,然后是对象的去重。首先是我们的测试数据:
var meta = [
0,
'0',
true,
false,
'true',
'false',
null,
undefined,
Infinity,
{
},
[],
function(){
},
{
a: 1, b: 2 },
{
b: 2, a: 1 },
];
var meta2 = [
NaN,
NaN,
Infinity,
{
},
[],
function(){
},
{
a: 1, b: 2 },
{
b: 2, a: 1 },
];
var sourceArr = [...meta, ... Array(1000000)
.fill({
})
.map(() => meta[Math.floor(Math.random() * meta.length)]),
...meta2];
下文中引用的所有sourceArr
都是上面的变量。sourceArr
中包含了1000008
条数据。需要注意的是NaN
,它是JS中唯一一个和自身严格不相等的值。
然后我们的目标是将上面的sourceArr
数组去重得到:
// 长度为14的数组
[false, "true", Infinity, true, 0, [], {
}, "false", "0", null, undefined, {
a: 1, b: 2}, NaN, function(){
}]
基础数据类型
1. ES6中Set
这是在ES6中很常用的一种方法,对于简单的基础数据类型去重,完全可以直接使用这种方法,扩展运算符 + Set
:
console.time('ES6中Set耗时:');
var res = [...new Set(sourceArr)];
console.timeEnd('ES6中Set耗时:');
// ES6中Set耗时:: 28.736328125ms
console.log(res);
// 打印数组长度20: [false, "true", Infinity, true, 0, [], [], {b: 2, a: 1}, {b: 2, a: 1}, {}, {}, "false", "0", null, undefined, {a: 1, b: 2}, {a: 1, b: 2}, NaN, function(){}, function(){}]
或是使用Array.from + Set
:
console.time('ES6中Set耗时:');
var res = Array.from(new Set(sourceArr));
console.timeEnd('ES6中Set耗时:');
// ES6中Set耗时:: 28.538818359375ms
console.log(res);
// 打印数组长度20:[false, "true", Infinity, true, 0, [], [], {b: 2, a: 1}, {b: 2, a: 1}, {}, {}, "false", "0", null, undefined, {a: 1, b: 2}, {a: 1, b: 2}, NaN, function(){}, function(){}]
**优点:**简洁方便,可以区分NaN
;
**缺点:**无法识别相同对象和数组;
简单的场景建议使用该方法进行去重。
2. 使用indexOf
使用内置的indexOf方法进行查找:
function unique(arr) {
if (!Array.isArray(arr)) return