4

js中的数组去重问题,被讨论都快烂掉了。网上也有很多方法,不过都大同小异,复制来复制去的。
当然这里不是讨论我是不是有什么新方法了,没有,只是在实践的时候发现一些问题,值得拿出来说说!
去重的思路有几种

1,第一个与后面所有的比较,发现重复的就删除掉,再取第二个与后面的比较,以此类推!
2,先排序,比较相邻的。
3,创建临时数组,原数组一个一个往里塞,若已存在就不塞了。
4,hash法,根据对象的属性不存在相同的特点,有点类似方法3。
….

当然这些具体代码网上很多,不一一列举!下面来探讨的是其中被人们忽略的一些问题。

方法1的代码如下

function arrayUnique(arr){ 
    for (var i=0;i‹arr.length;i++){
        for (var j=i+1;j‹arr.length-1;j++){
            if ( arr[j] === arr[i] ){
                arr.splice(j,1);
                j--;
            }
        }

    }
    return arr;
}

方法4的hash方法如下

function arrayUnique2(arr){
    var hash = {};
    var temp = [];
    for (var i=0;i‹arr.length;i++){
        if ( !hash[arr[i]] ){
            hash[arr[i]] = true;
            temp.push(arr[i]);
        }
    }
 /*
  for (var prop in hash){
   console.log(prop+'----'+typeof(prop))
 }
 */
    return temp;
}

虽然hash方法拥有非常搞的效率,但是存在一些问题,因为javascript中的数组是可以存储任意数据类型的值,就是可以是数字、字符串、或者数组、对象、函数等等。

实际测试中确实可以去除长得一样的数组或者对象,比如如下arr中的第四和第五个[1,2]会被去重,但问题来了。

var aa = 'aa',bb = 'bb';
var arr = [
    1,'1','abc',[1,2],[1,2],['1','2'],'1,2',['aa','bb'],[aa,bb],document,'[object HTMLDocument]',function (){return 1},function (){return 1;}
]
console.log(arrayUnique2(arr));//[1,'abc',[1,2],['aa','bb'],document,function (){return 1},function (){return 1;}]

如果两个对象的引用不同即使长得一样也不是全等的,这个我们知道,也可以说去掉长得相同的两个元素。

于是我将hash对象的属性跟属性的数据类型在函数中输出出来,发现对象属性或json键名的数据类型都是字符串类型的,并且每个被添加的属性,会被先隐式调用toString方法,即DOM中的document对象,变成对象的属性即json的键名的时候,隐式调用toString方法,这样就和'[object HTMLDocument]’是一样的了,数组去重的话,后面字符串类型的[object HTMLDocument]会被去掉。

同理[1,2],[1,2],[‘1′,’2′],’1,2’这四个值都会被认为是一样的而被去重。

数组最后面的两个函数,因为在后面的函数里加了个分号,否则也是相同。

所以会有这样的结论,在使用hash方法的时候,数组元素变成对象属性名或者json键名的时候,数据会先隐式调用toString方法变成字符串,然后成为对象的属性。而这样的后果就是,只要两个元素各自调用toString方法后的字符串相等,两个值遍认为是相同,即使两个值根本不想等。

所以这种hash去重的方法有局限性,即在去除所有值的数据类型相同的情况下,他是效率很高很好用,但是数据类型不同的情况下。还是老老实实用其他方法比较吧。(当然一般后端传到前端的数据,数据类型一般都是相同的。)

以上就是我对去重中遇到问题的一些思考,希望对大家有帮助,网上的东西,不能盲目拿来就用,要有自己的思考。


eric_bin
859 声望42 粉丝

web前端开发一枚...