Set 方法
对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用
new Set([1, 2, 3, 4, 5]) // [1, 2, 3, 4, 5]
// 它会自动去重
// 唯一值
new Set([1, 2, 3, 4, 5, 5, 5, 5]) // [1, 2, 3, 4, 5]
// 原始值
new Set([1, 2, '1', '1', null, null ,undefined, undefined]) // [1, 2, '1', null, undefined]
// 对象引用
var a = {}
new Set([a , a, a]) // [a]
// 它的问题是 不同的对象就不会去重
var a = {}
var b = {}
// 它就不会去重
new Set([a , b]) // [a, b]
new Set(array)去重后得到的不是数组,于是我们通常都会加上 Array.from(new Set(array)) 另一种写法是 [...new Set(array)]这个会尝试这个东西变成数组, ...表示解构然后放到数组里
对象的下标去重
var a = [???] // 里面的值不知道
function uniq(array){ ??? } // 里面内容不知道
//要求
uniq(a) // 把 a 传到你的 uniq 得到一个新数组,并且新的数组保证没有重复的元素
举例
对它进行去重 var a = [ 1, 2, 3, 3, 4, 4 ]
- 首先写一个函数,这个函数有一个返回值,返回新数组
function uniq(array){
var result = []
return result
}
- 这个的要求是把 a 传给到我这个函数里,这个函数对它进行数组去重
function uniq(array){
var result = []
var hash = {} // 新建一个空对象
for(let i = 0; i < array.length; i++){ // 遍历这个数组
// 我发现原数组里有 1 我 hash 的值就是 true ,发现原数组有啥我hash的值就是 true
// 在 hash 这个对象里,原数组的值被当作下标了,所以重复的部分就会被去掉
hash.push[array[i]] = true
}
// 接下来我就要把它变成数组弄出来
for(let key in hash){ // for...in 获取当前对象的所有键
result.push(key)
}
return result
}
console.log(uniq(a)) // 打印出 ['1', '2', '3', '4']
缺点
- 问题1
- 数组里的值数字变成字符串了
- 问题2
-
假设原数组中间不是数字呢?比如这种:
[1, 2, 3, 4, '5', 5]如何区分? 它会打印出
['1', '2', '3', '4', '5']没有办法区分它是数字还是字符串
举例:
var hash = {} hash[4] = '数字' // 打印出{4: '数字'} hash['4'] = '字符串' //有两个值吗? 不,打印的结果是 {4: '字符串'}
- 问题3
-
如果我里面有一个对象 比如
[1, 2, 3, 4, {name: 'object'}, 5]我是无法通过下标去重的,它打印出
[1, 2, 3, 4, "[object Object]", 5]因为这个方法的下标只支持字符串,当我以这个对象为下标的时候它会变成?
var hash = {} hash[{name: 'object'}] = true // 打印出 {[object Object]: true}为啥下标是
[object Object]因为所有对象变成字符串都是一个类似这种的字符串var a = {} a.toString() // [object Object]当看到这个对象的下标是对象的时候就会调用这个对象的
toString()方法,于是就变成了上面的样子了
总结
用对象的下标去重的最大问题是: 只能统计字符串(无法区分数字和字符串),无法统计对象
面试问到了该如何答?
首先我们应该看需求能不能用 ES6 的语法如果不能用 ES6 语法,我会选择一种不太完美的算法,这种算法是这样的
- 首先我们去遍历这个数组,然后把数组的值作为这个对象的下标储存起来,每遇到一个值就储存起来,然后如果发现是同一个值呢,就不用管它,如果是新的值就把这个值设为true,把这个 true 遍历一下放到新的数组里面 return 出来,就得到了新的数组,这是一种不太完美的数组去重方法,为何说它不太完美,第一个:它无法区分数字和字符串,第二个:如果这个数组里面有一个对象我们的去重方法就失败了,原因是我们的这个对象只支持字符串的下标,如果可以使用 ES6 的 Set 那就简单了,我们只需要 new Set(array), 然后得到的值 用Array.from()得到数组。