现在有这么一个重复数组:
const arr = ['a','a','b','a','b','c']
只推荐简单高效的方法,复杂繁琐的方法不做推荐
方法一:
const res = [...new Set(arr)]
Set类型是什么呢?
Set 是ES6新增的一种新集合类型。具体知识点可以看下面附录:
根据上面的知识点,我们可以得到:
console.log(...new Set(arr)) // a b c
所以去重也可以这么实现:
const res = Array.from(new Set(arr)) // Array.from将类数组转换成数组
// or
const res = Array.of(...new Set(arr)) // Array.of根据传入的参数生成数组
方法二:
var arr = ['apple','apps','pear','apple','orange','apps'];
var newArr = arr.filter(function(item,index){
return arr.indexOf(item) === index; // 因为indexOf 只能查找到第一个
});
方法三:
some + 循环去重
function distinct(list) {
let result = [list[0]];// 用于承接没有重复的数据,初始时将原始数组的第一个值赋给它。
for (let i = 1; i < list.length; i++) {
// 判断结果数组中是否存在一样的值,若果没有的话则将数据存入结果数组中。
if (!(result.some(val => list[i] === val))) {
result.push(list[i]);
}
}
return result;
}
方法四:
如果不能用ES6、5的语法。需要原生方法双重for循环去重:
function noRepeat(arr) {
for(var i = 0; i < arr.length-1; i++){
for(var j = i+1; j < arr.length; j++){
if(arr[i]===arr[j]){
arr.splice(j,1);
j--;
}
}
}
return arr;
}
方法五:
简单数组用includes去重
function noRepeat(arr) {
let newArr = [];
for(i=0; i<arr.length; i++){
if(!newArr.includes(arr[i])){
newArr.push(arr[i])
}
}
return newArr
}
附录 -Set
使用 new 关键字和 Set 构造函数可以创建一个空集合:
const s = new Set();
如果想在创建的同时初始化实例,则可以给 Set 构造函数传入一个可迭代对象(Array Map Set WeakMap WeakSet)。可迭代对象需要包含插入到新集合实例中的元素(Set 可以包含任何 JavaScript 数据类型作为值)。Set构造函数会迭代传入参数,去重后保存到集合实例中。
特点
Set 是唯一值的集合。
每个值在 Set 中只能出现一次。
一个 Set 可以容纳任何数据类型的任何值。
你可以把Set想像成跟数组一样,我们用size来输出Set集合的长度。
const s = new Set(['a','b','c','c']);
s.size; // 3 去重了一个c
const s2 = new Set();
s2.add('a')
s2.add('b')
s2.add('c')
s2.size // 3
与Array的区别
最根本的区别是数组是一个索引集合,这说明数组中的数据值按索引排序。
相比之下,set是一个键的集合。set不使用索引,而是使用键对数据排序(看下面forEach)。set 中的元素按插入顺序是可迭代的,它不能包含任何重复的数据。
对比Array的优势
在运行时间方面上Set占了很大的优势
查看元素:使用indexOf()或includes()检查数组中的项是否存在是比较慢的。
删除元素:在Set中,可以根据每项的的 value 来删除该项。在数组中,等价的方法是使用基于元素的索引的splice()。与前一点一样,依赖于索引的速度很慢。
保存 NaN:不能使用indexOf()或 includes() 来查找值 NaN,而 Set 可以保存此值。
删除重复项:Set对象只存储惟一的值,如果不想有重复项存在,相对于数组的一个显著优势,因为数组需要额外的代码来处理重复。
时间复杂度:
数组用来搜索元素的方法时间复杂度为0(N)。换句话说,运行时间的增长速度与数据大小的增长速度相同。
相比之下,Set用于搜索、删除和插入元素的方法的时间复杂度都只有O(1),这意味着数据的大小实际上与这些方法的运行时间无关。
具体解释与面试题强烈推荐阅读如何使用 Set 来提高JS代码的性能 - 知乎 (zhihu.com)
其他API
has()
查询Set实例是否存在某元素(返回布尔值):
const s = new Set();
s.add(1).add(2).add(3);
s.has(1); // true
delete()
删除某个元素
s.delete(1);
clear()
清空Set实例
s.clear();
Array.from(s); // []
迭代:
for of
for in不输出,因为它不是以下标为索引的集合
const s = new Set(['a','b','c','c']);
for (var n of s) {console.log(n)}
// a
// b
// c
forEach
s.forEach((t,i)=>console.log(t,i))
// a a
// b b
// c c
// 输出了键值对的结构
原生属性

可以看见Set实例的三个属性返回了枚举的类数组。
直接用Array.form转换
Array.from(s.keys())
// ['a', 'b', 'c']
Array.from(s.entries())
// [['a', 'a'],['b', 'b'],['c', 'c']]
Array.from(s.values())
// ['a', 'b', 'c']
附录-面试题
题目:
给定一个整数无序数组和变量 sum,如果存在数组中任意两项和使等于 sum 的值,则返回true。否则,返回false。例如,数组[3,5,1,4]和 sum = 9,函数应该返回true,因为4 + 5 = 9。
解题思路:
本题其实是为了找数组元素与sum的差值是否在数组里重复出现。

const s = new Set()
arr.some(t=> {
if (s.has(t)) {return true}
s.add(sum-t);return fasle
})
简洁点写:
const findSum = (arr, sum) =>
arr.some((set => n => set.has(n) || !set.add(sum - n))(new Set));