javascript对象深层复制

转载自:http://hi.baidu.com/lmh2072005/item/565af845e94cba38fa8960c9

javascript对象深层复制  
其实看到网上一个更新简单的方法 当是json对象时   直接先把json对象转换为json字符串 
然后复制该字符串后再把复制的字符串 转为json对象 
var a = jsonObj;
var b = JSON.stringify(a);
    b = JSON.parse(b);
对非json对象的对象就没什么用了 还有ie6/7不支持这两个方法。
下面这个就比较全面了 无限深层copy

function deepCopy(obj){

if(obj instanceof Array){

var newObj = [],

i = obj.length;

while(i--){

newObj[i] = arguments.callee.call(null,obj[i])

}

return newObj;

}else if(obj instanceof Date){

var newDate = new Date();

newDate.setTime(obj.getTime());

return newDate;

}else if(obj instanceof Object){

var newObj = {};

for(var i in obj){

newObj[i] = arguments.callee.call(null,obj[i])

}

return newObj;

}

else{

return obj;

}

}


后来发现其实还不够完善  

发现对于Function  Date  RegExp 类型的直接 return 就OK 了

完善后的:

function deepCopy(obj){
            if(obj instanceof Array){
                var arr = [],i = obj.length;
                while(i--){
                   arr[i] = arguments.callee.call(null,obj[i]);
                }
                return arr;
            }else if(obj instanceof Date || obj instanceof RegExp || obj instanceof Function){
                return obj;     //这几种类型传入的值非索引? 直接return
            }else if(obj instanceof Object){
                var a = {};
                for(var i in obj){             //标志1 
                   a[i] = arguments.callee.call(null,obj[i]);
                }
                return a;
            }else{
                return obj;
            }
        }


看了网上有些要在标志1处加个判断是否是自己的属性  obj.hasOwnProperty(i)

觉得不要加这个判断 因为既然是deepCopy 继承的属性应该也要复制的  。


下面是测试用例:

       var aClass=function(name){
            this.name = name;
        };
        aClass.prototype.fn=function(){
                console.log('abc');
        }
        var bClass = function(age){
            this.age=age;
        }
        bClass.prototype=aClass.prototype;
        var a = {
            'aa':function(s){return s+2;},
            'bb':new RegExp("\\d"),
            'cc':new Date('2012/01/01'),
            'dd':['sdsdf',123,function(){},new Date(),true,{'aa':{'aa':[1]}}],
            'ee':{'xx':function(){return 1},'ssdf':'adf'},
            'ff':'asdfasf',
            'gg':null,
            'hh':true,
            'ii':new bClass(20)
        };
        var b = deepCopy(a);
        //输出a
        console.log(a);
        //复制后改变a的值
        a.dd[2]=new RegExp("\\s");
        a.aa=function(xx){return 20;}
        a.bb='';
        a.cc=new Date();
        a.dd[3]=new Date('2012/01/01');
        a.ee.xx=function(){return 2+1;};
        a.gg={};
        a.dd[5]['aa']['aa'][0]=0;
        a.ff='aa';
        a.hh=0;
        //输出b
        console.log(b);

转载自:http://www.css88.com/archives/4818

js一般有两种不同数据类型的值:

基本类型(包括undefined,Null,boolean,String,Number),按值传递;

引用类型(包括数组,对象),按址传递,引用类型在值传递的时候是内存中的地址。例如:

1 var a={"a":1};
2  
3 var b=a;
4  
5 b["b"]=2;
6  
7 console.log(a);//{"a":1,"b":2};

如果你修改b的值,那么a变量的值也发生了变化。

克隆或者拷贝分为2种:浅度克隆(拷贝),深度克隆(拷贝);

浅度克隆:基本类型为值传递,对象仍为引用传递。

深度克隆:所有元素或属性均完全克隆,并于原引用类型完全独立,即,在后面修改对象的属性的时候,原对象不会被修改。

我的深度克隆代码如下:

01 function cloneObject(o) {
02         if(!o || 'object' !== typeof o) {
03             return o;
04         }
05         var temp;
06         if(o.constructor === Array){
07             //temp=o.concat();
08             temp = [];
09             var i = o.length;
10             while (i--) {
11                 temp[i] = cloneObject(o[i]);
12             }
13         }else if(o.constructor === Object){
14             temp = {}; 
15             for (var in o) {
16                 if(o.hasOwnProperty(k)){
17                     temp[k] = cloneObject(o[k]);
18                 }
19             }
20         }
21         return temp;
22     }

主要使用了递归。
不过代码看上去挺变扭的,被朋友批了一顿,数组本来就是对象,可以精简代码。优化了一下,欢迎拍砖:

1 function cloneObject(obj){
2     var o = obj.constructor === Array ? [] : {};
3     for(var in obj){
4         if(obj.hasOwnProperty(i)){
5             o[i] = typeof obj[i] === "object" ? cloneObject(obj[i]) : obj[i];
6         }
7     }
8     return o;
9 }

另:如果是一个简单的数组,元素中没有引用类型的值,可以直接用array.concat();或者array.slice(0);来深度拷贝一个数组,这样简单又高效。数组的concat()和slice()本来就会生成一个新的数组,原来的数组不会受影响。但是要注意的是你要确保被拷贝的数组中元素中没有引用类型的值。
=================2012-11-19 9:13更新===============
大家看redky评论把,最简单的深度克隆,很简单,很实用:
var s = JSON.stringify( obj );
var o = JSON.parse( s );




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值