JS的深拷贝和浅拷贝的造成原因以及解决方法

造成深拷贝和浅拷贝的主要原因还是因为数据存储的方式以及位置造成的。

在理解深拷贝和浅拷贝之前,咋们先了解下JavaScript有那些类型:

  1. 基本数据类型:Number、String、Boolean、undefined、Null、以及Es6新特性Symbol、或者未来Es10中的Bigint,一共是7种。

  2. 引用数据类型:Object,又细分为Object、Array、function、Data等等

粗糙来讲,一共是8种数据类型;

接下来我们讲讲基本和引用数据类型的存储原理:

  1. 基本数据类型:存储方法是直接将数据存储在栈中。
  2. 引用数据类型:存储方式是先在栈中开辟一个空间也就是咋们常说的入栈,存入一个地址,然后这个地址是指向堆中的某个位置,数据实际是存放在堆中。

有了上面的知识储备,咋们就好理解这个浅拷贝和深拷贝造成的原因了。比如咋们定义一个基本数据类型String,默认是直接在栈中存放数据。

var str = "这是一个字符串";
var newstr = str;
newstr = newstr + '1'
console.log(str, newstr);

咋们看效果,很明显修改newstr的值并不会影响str的值。这是由于在初始化newstr的时候,直接在栈中又给它开辟了一个新的空间。
在这里插入图片描述

咋们再来试试引用数据类型

var obj = {
	name: "老王",
	age: "30"
};
var newobj = obj;
newobj.name = "小王";
console.log(obj, newobj);

当我们将引用数据类型obj赋值给newobj后,修改newobj的属性,也会影响obj的属性。这就是浅拷贝。造成这种情况的原因是因为在赋值的过程中,仅仅是将栈中的地址进行了赋值,并没有在堆中给newobj重新开辟一个新的空间。导致obj和newobj指向同一个地址,这才是导致问题的所在。
在这里插入图片描述
讲完了造成原因,我们来讲讲如何去解决引用数据无法深拷贝这个问题。
在代码中运用递归的原因是,我们的对象是二维引用对象,但是只能对第一层进行深拷贝,很明显第二层并没有被深拷贝。

var obj = {
	name: "老王",
	age:"30",
	child: {
		name: "小王",
		age: "3"
	}
};
function copy_deep(obj){
	var newobj = obj instanceof Object ? {}: [];
	for(item in obj){
		if(obj.hasOwnProperty(item)){
			if(item instanceof Object){
			newobj[item] = copy_deep(obj[item]);
			}else{
				newobj[item] = obj[item];
			}
		}
	}
	return newobj;
}
var new_obj = copy_deep(obj);
new_obj.name = "老李"
new_obj.child.name = "小李"
console.log(obj, new_obj);

在这里插入图片描述
对于这种多层的引用数据类型,咋们也可以用JSON的stringify和parse来操作。

function deepCopy(obj){
    let _obj = JSON.stringify(obj);
    let obj2 = JSON.parse(_obj);
    return obj2;
}

var a = [1,[1,2],3,4];
var b = deepCopy(a);
b[1][0] = 2;
console.log(a,b);

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值