javascript数组去重方法终极总结

有时会碰上这种需求,需要将数组中重复的元素删除掉,而只保留一个。最先想到的办法很可能就是用2个for循环来做比较然后去除掉重复的元素,代码如下所示:


方法1:




复制代码 代码如下:



Array.prototype.distinct = function(){


 var arr = [],


      len = this.length;


 for ( var i = 0; i < len; i++ ){
  for( var j = i+1; j < len; j++ ){
   if( this === this[j] ){
    j = ++i;
   }
  }
  arr.push( this );
 }
 return arr;
};



使用方法1如果碰到数据比较多时性能上会差很多。那么请继续看下面的方法。


方法2:




复制代码 代码如下:



Array.prototype.distinct = function(){


 var self = this,


  arr = self.concat().sort(); // 创建一个新数组并排序


 arr.sort(function( a, b ){


  if( a === b ){


   var n = self.indexOf( a ); //获取索引值


   self.splice( n, 1 );


  }


 });


 return self;


};




方法2使用了 sort 的自定义回调函数,也用到了 indexOf 这个IE6/7/8不支持的方法。当然,indexOf可以自己模拟,但是更大的问题是IE6/7/8的sort方法和标准浏览器之间也有差别。在IE6/7/8中使用 sort 方法的自定义回调函数陷阱比较多,上面的自定义 sort 的回调函数的代码在IE6/7/8中会直接报“缺少数字”的错误,回调函数的返回是NaN的话就会报这个错,因为理论上 sort 的回调函数只能返回整数。就算忽略返回值的问题还是有其他问题,最后也没有过多的去纠结了,方法2在IE6/7/8中行不通。


从愚人码头那里看来了方法3,下面是他的代码:



复制代码 代码如下:



Array.prototype.delRepeat=function(){


 var newArray=[];


 var provisionalTable = {};


 for (var i = 0, item; (item= this) != null; i++) {


        if (!provisionalTable[item]) {


            newArray.push(item);


            provisionalTable[item] = true;


        }


    }


    return newArray;


};




方法3使用了一个临时的对象来存储数组的元素,如果碰上重复的数组元素,将会忽略掉。但是,如果碰到下面这种数组:




复制代码 代码如下:



var arr = [ ‘firefox’, 1, ‘1’ ];




上面的数组如果用方法3会误将 1 和 “1” 当成重复元素而删除掉,于是有将方法3做了一点点的小修改,可以解决这个BUG。
方法3的修改版:




复制代码 代码如下:



Array.prototype.distinct = function(){


 var arr = [],


  obj = {},


  i = 0,


  len = this.length,


  result;


 for( ; i < len; i++ ){
  result = this;
  if( obj[result] !== result ){
   arr.push( result );
   obj[result] = result;
  }
 }


 return arr;
};



之后又看了愚人码头文章后面的评论,该方法和Rekey提供的方法是一样的,但是这个方法也有BUG,如果碰到这样的2B数组就杯具了:




复制代码 代码如下:



var arr = [ ‘firefox’, 1, ‘1’, 1 ];



SyntaxHighlighter.highlight();