zoukankan      html  css  js  c++  java
  • 关于对象深拷贝和数组去重的问题...

    中秋最后一天假期,还是憋屈在家里,没事可做,发发关于两个看似很基础却又很有意义的两个问题的一点感想,如题...

    一.对象深拷贝:

    对应的浅拷贝,对象是通过地址指向来获得引用的,所以单纯的用一个新对象指向源对象就是浅拷贝,对新对象的操作同样会影响的源对象。好比小明有个U盘,里面装有一些资料,一天,小红也需要这个U盘里的资料,于是拿过来改了里面的资料,结果小明再用时,里面资料就变了,因为两个人用的其实是同一个u盘嘛... 如下:

    var obj = {a:'a'};
    var obj1 = obj;
    obj.a = 'a1';
    alert(obj.a);
    alert(obj1.a);
    

    运行

    那么怎么样才能资料各自私有而不影响对方呢,显而易见嘛,让小红也去买个u盘,并把资料也拷一份到她的u盘里,各用个的就行了。于是:

    function clone(myObj)
    {
        if(typeof(myObj) != 'object' || myObj == null) return myObj;
        var myNewObj = new Object();
        for(var i in myObj) myNewObj[i] = clone(myObj[i]);//递归调用,当对象中又有对象时
        return myNewObj;
    }
    var obj = {a:'a'};
    var obj1 = obj;
    var obj2 = clone(obj);
    obj.a = 'a1';
    alert(obj.a);
    alert(obj1.a);
    alert(obj2.a);
    

    运行

    至此,区别也很明显了,obj1浅拷贝由于是访的同一个对象,故改变源对象obj,新对象obj1也随之改变。而深拷贝obj2是新建了一个对象实例,与源对象obj互不干扰。

    二.关于数组去重

    网上很流行一种解法,如下:

    Array.prototype.filter = function(){
    	for(var i=0,temp={},result=[],ci;ci=this[i++];){
    		if(temp[ci])continue;
    		temp[ci]=1;
    		result.push(ci);
    	}
    	return result;
    }
    var aa=['1','2','3','1','2'];
    alert(aa.filter());
    

    运行

    它其实是用了对象的特性,把每个数组元素当做一个对象的属性来判断是否存在,这样做有个好处是不用二次遍历数组。然而,乍一看结果没问题,可是一旦数组里有了number,布尔值,对象等作为元素的时候,就会发现问题了。
    原因在于:对象则要求其属性值必须为字符串,如果提供给对象的属性不是字符串,那么则会自动调用 toString 方法转化为字符串形式,于是,严格来讲,这种方法只能在数组元素全为字符串时才成立

    我们再看看jquery的源码是怎么实现数组去重的方法的:

    unique: function( array ) {  
            var ret = [], done = {};  
            try {  
                for ( var i = 0, length = array.length; i < length; i++ ) {  
                    var id = jQuery.data( array[ i ] );  
      
                    if ( !done[ id ] ) {  
                        done[ id ] = true;  
                        ret.push( array[ i ] );  
                    }  
                }  
      
            } catch( e ) {  
                ret = array;  
            }   
            return ret;  
        },  
    

    乍一看,其实思路跟我上面说的方法是一样的,可是别忘了很重要的一点,var id = jQuery.data( array[ i ] );这一句,其实是把每个数组元素都转换成了节点数组再做的判断。

    所以,如果把安全性放在首位,效率次之的话,数组去重还是应该老老实实二次遍历数组,如下:

    function undulpicate(array){  
        for(var i=0;i<array.length;i++) {  
            for(var j=i+1;j<array.length;j++) {  
                //注意 ===  
                if(array[i]===array[j]) {  
                    array.splice(j,1);  
                    j--;  
                }  
            }  
        }  
        return array;  
    } 
    

    当然,如果能确定数组元素类型,大可不必这样做,毕竟二次遍历在数据量大的时候是个不小的消耗。。
    此外,貌似hash查找可以减少一次遍历...具体还没想过...唉,今天就到此位置吧

  • 相关阅读:
    玩转Android状态栏
    自己制作 Android Vector Asset 矢量图
    android studio配置模拟器
    Android数据库使用指南(下)
    Android数据库使用指南(上)
    四种常见的 POST-------- content-type数据提交方式
    json格式化
    js删除cookie的方法
    js中box和box()的区别
    synchronized加static区别
  • 原文地址:https://www.cnblogs.com/hongru/p/1833928.html
Copyright © 2011-2022 走看看