JS对象深拷贝与浅拷贝之解析

在计算机中,有两种存储数据的方式,一种是字符串类型,另一种是引用类型。其中字符串类型是存储在内存的栈中,而引用类型是存储在内存的堆中,栈中的变量通过指针可以指向堆中的引用类型对象。

浅拷贝指将对象B直接赋值给对象B,两者在栈中是两个变量,却同时指向堆中的同一个对象。当改变其中一者时,另一者也同步进行改变。

let obj1 = {a:1};
let obj2 = obj1;
obj2.a = 10;
console.log(obj1); //{a:10}
console.log(obj2); //{a:10}

可以看出,当进行完对象的赋值操作后,如果在改变赋值对象的时候不希望破坏被赋值对象,这种方式不能达到预期要求,这就是浅拷贝。

深拷贝是指根据原对象在堆中创建一个新的引用类型,在栈中创建一个变量通过指针指向这个新的引用类型,因而与原对象完全脱离了关联,当改变其中一者时,另一者不随其进行改变。

深拷贝的方式有以下几种:

1、ES6方法;

let obj1 = {a:1,b:2,c:3};
let obj2 = {...obj1};
obj2.a=100;
console.log(obj2);//{a:100,b:2,c:3}
console.log(obj1);//{a:1,b:2,c:3}

这种方式不适合引用类型嵌套引用类型的方式。即:

let obj1 = {
	a:{
		b:1
	}
}
let obj2 = {...obj1};
obj2.a.b = 100;
console.log(obj2); //{a:{b:100}}
console.log(obj1);//{a:{b:100}}

2、JSON.stringfy和JSON.parse,这种方式同样不适合引用类型嵌套引用类型的方式

let obj1 = {a:1,b:2,c:3};
let obj2 = JSON.parse(JSON.stringfy(obj1));
obj2.a=100;
console.log(obj2);//{a:100,b:2,c:3}
console.log(obj1);//{a:1,b:2,c:3}

3、Object.assign(),这种方式同样不适合引用类型嵌套引用类型的方式

let obj1 = {a:1,b:2,c:3};
let obj2 = Object.assign({},obj1);
obj2.a=100;
console.log(obj2);//{a:100,b:2,c:3}
console.log(obj1);//{a:1,b:2,c:3}

4、通过jQuery.extend或loadash的cloneDeep

var objects = [{ 'a': 1 }, { 'b': 2 }];
 
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false

5、最靠谱的一种方式当然是通过手写函数来实现,适合各种类型的对象。

function deep_clone(obj){
	if(typeof obj!=='object') return obj;
	let newObj = obj.constructor===Array?[]:{};
	for(let i in obj){
		if(typeof obj[i]==='object'){
			newObj[i]=deep_clone(obj[i]);
		}else{
			newObj[i]=obj[i];
		}
	}
	return newObj;
}
let obj = {a:1};
let obj2 = deep_clone(obj);
obj2.a=100;
console.log(obj2);//{a:100};
console.log(obj);//{a:1};

如果文中有不妥之处,欢迎各位大神指正。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值