js对象的深度克隆

js对象的深度克隆

基本类型和引用类型的复制

对于复制相信大家都不陌生,复制了有两种情况:引用类型的复制与基本类型的复制。其中基本类型的复制:在变量对象上创建一个新值,然后将该值复制到新值分配的位置上去。这两个变量可以参与任何操作而不互相影响。且二者都存储在栈内存中。
而对于引用类型的复制,传递的仅仅是一个指向原引用类型的的地址(类似指针的概念)。他是仅仅是对地址的引用,而非间接寻址。这两个变量参与任何操作都会互相影响,原对象存储于堆内存,复制后对象存储于栈内存中。

引用类型的深度克隆

这两天因为准备面试所以刷了一下题。遇到一个出镜率很高的boy:对象的深度克隆。本以为拿来网上别人写的答案理解一下就可以,但在运行代码时总会出现或多或少的问题。所以自己又花了半天时间调试出一个自己的clone。可能会有或多或少的情况没有考虑到,希望大家多多指点。

参考案例

首先,我先放我参考的一个博友 u010599762(http://m.blog.csdn.net/article/details?id=40144017)的clone方法。

 {
     var o;
     if(obj1.constructor==Object)
      { 
        o = new obj1.constructor() ;
      }
    else
     {
      o = new obj1.constructor(obj1.valueOf())
     }
    for(var key in obj1)
    {
      if(obj1[key]!=o[key])
       {
          if(typeof obj1[key] =="object"&&obj1[key]!=null)
            o[key] = clone2(obj1[key]) ;
         else
            o[key] = obj1[key] ;
      }
   }
return o ; 
}

测试用例:

       function Obj1(){
        this.a = 1 ;
        this.b = 2 ;
        this.view = {
            'name':'zhangsan'
        };
    }
    Obj1.prototype.arr = [1,2,3,4] ;
    var oNew = new Obj1();

    var copy = clone2(oNew) ;
    copy.view = {
        age : 10
    } ;

    console.log('copy:'+copy.view);
    console.log('oNew:'+oNew.view);

    var oNew2 = {
        name : 'pan',
        position : 'student'
    }
    var copy2 = clone2(oNew2);
    copy2.name = 'wang';
    console.log(copy2.name);//'wang'
    console.log(oNew2.name);//'pan'
问题一

对于普通对象的克隆是没什么问题,但是对于数组的克隆处理的就有点问题了。在测试用例中

Obj1.prototype.arr = [1,2,3,4] ;
    var oNew = new Obj1();
    var copy = clone2(oNew) ;

我用firebug调试了一下:
发现会出现这样的问题:copy 的数组对象arr 被克隆成了[[1,2,3,4]]。这是由于o = new obj1.constructor(obj1.valueOf());将传入数组作为一个对象进行处理了。
这里写图片描述

问题二

而且对于以字面量形式生成的对象也没有解决。
测试代码:

  var oNew2 = {
        name : 'pan',
        position : 'student'
    }
    var copy2 = clone2(oNew2);
    console.log(copy2);
    console.log(oNew2);

这里写图片描述

修改过的代码

于是帮我把程序进行了修改:

function clone2(obj1) {
        var o;
        if(obj1.constructor==Object){//当obj1为字面量形式生成对象情况。
            o = new obj1.constructor() ;
            for(var key in obj1)
            {
                if(o[key] != obj1[key]) {
                    if(typeof obj1[key] =="object"&&obj1[key]!=null)
                        o[key] = clone2(obj1[key]) ;
                    else
                        o[key] = obj1[key] ;
                }
            }
        } else if(obj1.constructor == Array) {
        //obj1是数组时的情况
                var array = [];
                obj1.forEach(function(value) {
                    if(typeof(value) != "object")
                        array.push(value);//数组元素为基本类型
                     else
                        array.push(clone2(value));//数组元素为引用类型
                });
                o = array;
        } else {//以构造函数形式new出的对象
            o = new obj1.constructor(obj1.valueOf());
            //当obj1为内置对象时obj1.valueOf()的参数作用才真正使用。否则,这里传递的参数就不会被用到。
            for(var key in obj1){
                if(!obj1.hasOwnProperty(key)) {
                    if(typeof obj1[key] =="object"&&obj1[key]!=null)
                        o[key] = clone2(obj1[key]) ;
                    else
                        o[key] = obj1[key] ;
                }
            }
        }
        return o ;
    }

这里有一点需要注意。在处理字面量对象(obj1.constructor==Object)与构造函数对象时我们队对象本身属性的判断方式不同。
对于字面量对象:
if(o[key] != obj1[key])
对于构造函数对象:
if(!obj1.hasOwnProperty(key))
这里是用于处理字面量问题的。

自述

小白一枚,代码可能漏洞百出,大家不喜可提点一下,但勿喷,会打击伦家写博客的热情滴。。。。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值