JS深度拷贝

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS深度拷贝相关的知识,希望对你有一定的参考价值。

浅度克隆:基本类型为值传递,对象仍为引用传递。
深度克隆:所有元素或属性均完全克隆,并于原引用类型完全独立,即,在后面修改对象的属性的时候,原对象不会被修改。
一、原始类型克隆
1、数值的克隆
var x=1;
var y=x;
y=2;
console.log(x); //1
console.log(y); //2
2、字符串的克隆
var x="abc";
var y=x;
y="def";
console.log(x); //abc
console.log(y); //def
3、布尔值的克隆
var x = true;
var y = x;
y=false;
console.log(x); //true
console.log(y); //false
由于原始类型存储的是对象的实际数据,因此我们可以通过简单的复制方式即可得到正确的结果,而且不影响之前的对象。
 
 
二、对象类型克隆
1、数组的克隆
var x = [1,2,3];
var y = x;
console.log(y); //[1,2,3]
y.push(4);
console.log(y); //[1,2,3,4]
console.log(x); //[1,2,3,4]
对象类型存储的是对象的引用地址,而把对象的实际内容单独存放,因为对象类型通常比较庞大,这是数据开销和内存开销优化的手段。因此我们不能像原始数据类型一样简单的赋值,而应该遍历数据中的每一个元素,将其中的每一个原始数据类型复制过去,做法如下:
var x = [1,2,3];
var y = [];
for (var i = 0; i < x.length; i++) {
y[i]=x[i];
}
console.log(y); //[1,2,3]
y.push(4);
console.log(y); //[1,2,3,4]
console.log(x); //[1,2,3]
 
2、对象的克隆
参照数组的克隆,我们采用同样的思想进行对象的克隆:
var x = {a:1,b:2};
var y = {};
for(var i in x){
y[i] = x[i];
}
console.log(y); //Object {a: 1, b: 2}
y.c = 3;
console.log(y); //Object {a: 1, b: 2, c: 3}
console.log(x); //Object {a: 1, b: 2}
 
3、函数的克隆
var x = function(){console.log(1);};
var y = x;
y = function(){console.log(2);};
x(); //1
y(); //2
由于函数对象克隆之后的对象会单独复制一次并存储实际数据,因此并不会影响克隆之前的对象。所以采用简单的复制“=”即可完成克隆。
 
三、通用的对象克隆
通过上面的分析,我们知道对于原始类型以及对象类型中的函数是可以直接通过“=”复制来实现克隆,而对于对象和数组,则需要遍历每一个元素,如果元素为对象或数组,则需继续遍历,直到为原始类型或函数,则直接通过“=”复制。
function deepcopy(p,c){
var c = c||{};
for(var i in p){
if(typeof p[i] ==="object"){
c[i]=(p[i].constructor===Array)?[]:{};
deepcopy(p[i],c[i]);
}else{
c[i]=p[i];
}
}
return c;
}

 

我们测试一下:

新建一个对象:

var parent={
numbers:[1,2,3],
a:{
name:"zzh",
age:"21",
job:"Web"
}
}
拷贝该对象并输出:
var copy = deepcopy(parent);
copy.numbers.push(4,5,6,7,8,9);
console.log(parent);
console.log(copy);
技术分享

对象被成功复制,并且未改变原对象

以上是关于JS深度拷贝的主要内容,如果未能解决你的问题,请参考以下文章

js算法之深度拷贝和深度比较

js变量深度拷贝

js 深度拷贝

js实现深拷贝

JS深度拷贝

js 对象的浅拷贝和深拷贝