JavaScript中的深度克隆

javascript的一切实例都是对象,只是对象之间稍有不同,分为原始类型和合成类型。原始类型对象指的是字符串(String)、数值(Number)、布尔值(Boolean),合成类型对象指的是数组(Array)、对象(Object)、函数(Function)。

既然对象分为这两类,他们之间的最大差别是复制克隆的差别。普通对象存储的是对象的实际数据,而引用对象存储的是对象的引用地址,而把对象的实际内容单独存放,因为引用对象通常比较庞大,这是数据开销和内存开销优化的手段。通常初学者很难理解这部分内容,就像对象的原型一样,也是同一个概念。对象的原型也是引用对象,把原型的方法和属性放在单独内存当中,而对象的原型链则指向这个内存地址。尽管这部分内容比较拗口复杂,那其中的原理都是一致的,目的也一致。

1、原始类型对象的克隆

1.1、字符串的克隆

var x="1";
var y=x;
y="2"; 
// "1"
alert(x);
// "2"
alert(y);

1.2、数值的克隆

var x=1;
var y=x;
y=2; 
// 1
alert(x);
// 2
alert(y);

1.3、布尔值的克隆

var x=true;
var y=x;
y=false;
 // true
alert(x);
// false
alert(y);

2、合成类型对象的克隆

2.1、数组的克隆

如果采用普通克隆:

var x=[1,2];
var y=x;
y.push(3); 
// 1,2,3
alert(x); 
// 1,2,3
alert(y);

由上可知,原始数组x,克隆数组y,修改了克隆数组y,但也同时修改了原始数组x,这就是引用对象的特点。那么如何才能达到完整的数组克隆呢?

var x=[1,2];
var y=[];
var i=0;
var j=x.length;
for(;i<j;i++){	
    y[i]=x[i];
}
y.push(3); 
// 1,2
alert(x); 
// 1,2,3
alert(y);

这样,克隆数组y,原始数组x,两个数组互补干扰,实现了完整的数组克隆。

2.2、对象的克隆

和数组的克隆同理,对象的完整克隆如下:

var x={1:2,3:4};
var y={};
var i;
for(i in x){	
    y[i]=x[i];
}
y[5]=6; 
// Object {1: 2, 3: 4} 
console.log(x); 
// Object {1: 2, 3: 4, 5: 6} 
console.log(y);

2.3、函数的克隆

var x=function(){alert(1);};
var y=x;
y=function(){alert(2);};

// function(){alert(1);};
alert(x);

// y=function(){alert(2);};
alert(y);

函数的克隆,使用“=”符号就可以了,并且在改变克隆后的对象,不会影响克隆之前的对象,因为克隆之后的对象会单独复制一次并存储实际数据的,是真实的克隆。

3、完整的对象克隆

根据1和2,总结一下完整的对象克隆,包括克隆普通对象、引用对象。在写这个方法之前,我们必须想到的是,克隆引用对象必须采用完整克隆(深度克隆),包括对象的值也是一个对象也要进行完整克隆(深度克隆)。

完整的对象克隆又称为深度对象克隆、对象的深度克隆、对象的深度复制等等。

  1. function clone(obj)
  2. {
  3.     var o,i,j,k;
  4.     if(typeof(obj)!="object" || obj===null)return obj;
  5.     if(obj instanceof(Array)){
  6.          //如果当前遍历到的是数组的话
  7.          o=[];
  8.           i=0;j=obj.length;
  9.           for(;i<j;i++)
  10.           {
  11.                  if(typeof(obj[i])=="object" && obj[i]!=null)
  12.                  {
  13.                      o[i]=arguments.callee(obj[i]);
  14.                  }
  15.                 else
  16.                  {
  17.                      o[i]=obj[i];
  18.                  }
  19.            }
  20.     }
  21.     else
  22.     {
  23.    //如果当前遍历到的是一个obj的话, 创建一个obj对象, 遍历当前obj的属性
  24.         o={};
  25.         for(i in obj){
  26. //遍历当前obj的属性
  27.             if(typeof(obj[i])=="object" && obj[i]!=null){
  28.                 o[i]=arguments.callee(obj[i]);
  29.             }
  30.             else{
  31.     //遍历到obj内的属性, 直接使用"="进行赋值操作即可
  32.                 o[i]=obj[i];
  33.              }
  34.          }
  35.      }
  36. return o;
  37. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值