Javascript中的深拷贝和浅拷贝最根本的区别在于是否真正获取了实体对象的复制实体
例如:B复制了A
浅拷贝:修改A时,B也会跟着发生变化(指针还是指向A)
深拷贝:修改A时,B不会发生变化(已经拿到A的实体,你改任你改)
区别
浅拷贝:只是增加一个指针指向已存在的内存地址,原地址发生改变,浅拷贝出的对象也会发生改变
深拷贝:增加了一个指针并开辟了新的内存,指向新的内存地址
浅拷贝容易出现释放内存时释放了同一个内存的错误,深拷贝就不会
浅拷贝实现方法
(1)直接赋值:
var obj1={
a:1,
b:2
}
var obj2=obj1;
console.log(obj2);
输出:
此时改变原值:
obj1.a=3;
console.log(obj1);
console.log(obj2);
输出:
(2)for…in循环
function simpleCopy(obj1) {
var obj2 = Array.isArray(obj1) ? [] : {};
for (let i in obj1) {
obj2[i] = obj1[i];
}
return obj2;
}
var obj1 = {
a: 1,
b: 2,
c: {
d: 3
}
}
var obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.d = 4;
alert(obj1.a); // 1
alert(obj2.a); // 3
alert(obj1.c.d); // 4
alert(obj2.c.d); // 4
(3)Object.assign方法:
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign(obj);
obj1.a = 3;
console.log(obj.a) // 3
深拷贝实现方法
(1)递归:
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a=[1,2,3,4],
b=deepClone(a);
a[0]=2;
console.log(a,b);
输出:
(2) 通过JSON对象来实现:
function deepClone2(obj) {
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone;
}
该方法的缺点:无法深拷贝对象中的方法,会显示undefined
(3)通过jQuery的extend方法:
var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝
(4)手动实现深拷贝:
let obj1 = {
a: 1,
b: 2
}
let obj2 = {
a: obj1.a,
b: obj1.b
}
obj2.a = 3;
alert(obj1.a); // 1
alert(obj2.a); // 3
(5)slice实现对数组的深拷贝:
var arr1 = ["1","2","3"];
var arr2 = arr1.slice(0);
arr2[1] = "9";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );
当数组里面的值是基本数据类型,比如String,Number,Boolean时,属于深拷贝
当数组里面的值是引用数据类型,比如Object,Array时,属于浅拷贝
(6)concat实现对数组的深拷贝
var arr1 = ["1","2","3"];
var arr2 = arr1.concat();
arr2[1] = "9";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );
var arr1 = [{a:1},{b:2},{c:3}];
var arr2 = arr1.concat();
arr2[0].a = "9";
console.log("数组的原始值:" + arr1[0].a ); // 数组的原始值:9
console.log("数组的新值:" + arr2[0].a ); // 数组的新值:9
(7)var newObj = Object.create(oldObj):
function deepClone(initalObj, finalObj) {
var obj = finalObj || {};
for (var i in initalObj) {
var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
if(prop === obj) {
continue;
}
if (typeof prop === 'object') {
obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
} else {
obj[i] = prop;
}
}
return obj;
}