本文详细解析七种JavaScript数组去重方案,涵盖Set、双层循环splice、indexOf、includes、filter结合indexOf、Map及对象属性法。重点对比各方法对NaN和undefined的处理差异,揭示includes与Map底层对NaN判等的特殊机制,帮助开发者根据数据类型选择最优去重策略。
示例:对包含多种数据类型的数组进行去重处理。
const arr = [1, 2, 2, 'abc', 'abc', true, true, false, false, undefined, undefined, NaN, NaN]
1. 利用Set()与Array.from()
- Set对象是一个值集合,支持按插入顺序迭代其元素。Set中的每个值仅出现一次,确保元素唯一性。
- Array.from()方法用于将类数组对象或可迭代对象转换为新的浅拷贝数组实例。
const result = Array.from(new Set(arr))
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]
注意:上述方法对NaN和undefined类型的去重同样有效。这是因为Set允许存储NaN和undefined,且Set内部将NaN视为相同的值(尽管在JavaScript中NaN !== NaN为真)。
2. 利用双层循环结合splice方法
通过双层循环逐一比较数组元素,并利用splice方法移除重复项。此方法无法对NaN进行去重,因为比较时NaN !== NaN成立。
function removeDuplicate(arr) {
let len = arr.length
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (arr[i] === arr[j]) {
arr.splice(j, 1)
len-- // 减少循环次数提高性能
j-- // 保证j的值自加后不变
}
}
}
return arr
}
const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN, NaN ]
3. 利用数组的indexOf方法
创建一个新数组,遍历原数组并将元素存入新数组。存入前检查新数组中是否已存在当前元素,若不存在则存入。该方法同样无法处理NaN。
indexOf()方法返回调用它的String对象中指定值第一次出现的索引,从fromIndex 位置开始搜索。若未找到该值,返回-1。
function removeDuplicate(arr) {
const newArr = []
arr.forEach(item => {
if (newArr.indexOf(item) === -1) {
newArr.push(item)
}
})
return newArr // 返回一个新数组
}
const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN, NaN ]
4. 利用数组的includes方法
此方法的逻辑与indexOf方法去重类似,但使用includes方法来判断是否包含重复元素。
includes()方法用于判断数组是否包含指定值,若包含返回true,否则返回false。
function removeDuplicate(arr) {
const newArr = []
arr.forEach(item => {
if (!newArr.includes(item)) {
newArr.push(item)
}
})
return newArr
}
const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]
注意:includes能检测数组中包含NaN,这与其底层实现有关。如下代码所示,判断是否包含某元素时会调用sameValueZero方法进行比较,若为NaN,则使用isNaN()进行转换处理。
简单测试includes()对NaN的判断结果:
const testArr = [1, 'a', NaN]
console.log(testArr.includes(NaN)) // true
5. 利用数组的filter()结合indexOf()
filter方法将满足条件的元素存放至新数组,并结合indexOf方法进行判断筛选。
filter()方法创建一个新数组,包含所有通过所提供函数测试的元素。
function removeDuplicate(arr) {
return arr.filter((item, index) => {
return arr.indexOf(item) === index
})
}
const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined ]
注意:此处输出结果不包含NaN,是因为indexOf()无法正确判断NaN,即arr.indexOf(item) === index返回false。测试如下:
const testArr = [1, 'a', NaN]
console.log(testArr.indexOf(NaN)) // -1
6. 利用Map()
Map对象是JavaScript提供的一种数据结构,结构为键值对形式。将数组元素作为Map的键存入,前端培训然后结合has()和set()方法判断键是否重复。
Map对象用于保存键值对,并能记住键的原始插入顺序。任何值(对象或原始值)均可作为键或值。
function removeDuplicate(arr) {
const map = new Map()
const newArr = []
arr.forEach(item => {
if (!map.has(item)) { // has()用于判断map是否包为item的属性值
map.set(item, true) // 使用set()将item设置到map中,并设置其属性值为true
newArr.push(item)
}
})
return newArr
}
const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]
注意:使用Map()也可对NaN去重,原因是Map在判断时认为NaN与NaN相等,其余所有值根据===运算符的结果判断是否相等。
7. 利用对象
其实现思想与Map()类似,主要利用对象属性名不可重复的特性。
function removeDuplicate(arr) {
const newArr = []
const obj = {}
arr.forEach(item => {
if (!obj[item]) {
newArr.push(item)
obj[item] = true
}
})
return newArr
}
const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN ]
至此,关于七种JS实现数组去重方式的介绍结束。更多相关JS数组去重内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!