对JS中深拷贝、浅拷贝的一些理解以及深拷贝常用的一些方法

1.首先我们先区分一下什么是深拷贝、什么是浅拷贝?
假设B复制了A,当修改A时,看B是否发生了变化,若B也跟着变了,那么就说明这是浅拷贝;若B没变,则说明是深拷贝。
2.通过阐述堆栈、基本数据与引用数据来理解深拷贝和浅拷贝。
(1)基本数据类型和引用数据类型的数据存储是不一样的
(2)基本数据类型——名、值都存储在栈内存中。

let a = 1;

当b复制a时,即b = a;栈内存会开辟一个内存空间,此时修改a = 2,对b不会造成影响。但是这也不能算深拷贝,因为深拷贝针对较为复杂的Object类型数据。
(3)引用数据类型——属性名存储在栈内存中,属性值存储在堆内存中,但是栈内存会提供一个引用的地址指向内存中的值。

let a = [0,1];

当b = a,进行复制时,其实复制的是a的引用地址,而并非堆里面的值,当a[0] = 1进行修改时,由于a,b指向的是同一个地址值,b自然也变了,这就是浅拷贝。
若在内存中开辟一个新的内存专门为b存放值,就像基本类型一样,就起到了深拷贝的效果了。
3.简单总结一下:
浅拷贝:只是将对象中的数据引用下来,依旧指向同一个存放地址,拷贝之后的数据修改后,也会影响到原数据中的对象数据。
深拷贝:将对象中所有的数据拷贝下来,对拷贝之后的数据进行修改不会影响到原数据。
4.下面简单介绍一下深拷贝的几种方法:
(1)利用递归进行深拷贝:

function deepClone(obj){
	let objectClone = Array.isArray(obj)?[]:{};  //判断obj是否是数组,若是,则是[],若不是,则是{}
	if(obj&&typeof obj === 'object'){  //判断obj是否是一个对象,若只用typeof obj === 'object',不能完全判断obj是否是对象,考虑null,null的类型是对象,但它其实并非对象。null转化为数字类型是0,转换为布尔值为false。
		for(key in obj){
			if(obj.hasOwnProperty(key)){  //判断对象属性里是否包含某个key,key为字符串
				if(obj[key]&&typeof obj[key] === 'object'){  //拷贝的对象不为空
					objClone[key] = deepClone(obj[key]);  //若对象的属性是复杂对象,则继续递归复制
				}
				else{
					objClone[key] = obj[key];
				}
			}
		}
	}
return objClone;
}

实现思路:
[1]将要拷贝的数据obj以参数的形式传参。
[2]声明一个变量来存储我们拷贝出来的内容,且判断需要拷贝的是数组还是对象。
[3]判断是否是null,若是,则直接返回。
[4]遍历每个属性,判断每个属性是否是复杂对象,若是,再次递归,若不是,直接复制。
(2)JSON对象实现深拷贝:

function clone(obj){
	var copyObj = JSON.stringify(obj);  //将对象转换为字符串
	var objCopy = JSON.parse(copyObj);  /将JSON字符串转换为JSON对象
	return objCopy;
}

注意事项:
[1]如果obj里面有RegExp、Error对象,则序列化(JS中的对象转化为字符串)的结果将只得到空对象。
[2]如果obj里面有时间对象,则JSON.Stringify后再JSON.Parse的结果,时间将只是字符串,而不是时间对象。
[3]如果obj里面有函数、undefined,则序列化的结果会把undefined丢失。
[4]如果obj里面有NaN、infinity和-infinity,则序列化的结果会变成null。
[5]无法处理function,无法处理循环引用对象。

//循环引用对象
var a = {'name':'zzz'};
var b = {'name':'vvv'};
a.child = b;
b.parent = a;
//注意:这里的a和b都是循环引用对象,JSON.stringify()对该类对象序列化会报错

(3)使用jQuery(extend)方法实现深拷贝:

var obj = {
	a:10,
	b:function(){
		console.log(this.a)
	}
}
var newObj = $.extend(true,{},obj);

注意:$.extend中的true为深拷贝,false为浅拷贝,其实是把第二个对象上面的属性和对象覆盖到第一个对象上。
(4)使用Object.assign()实现深拷贝:

var obj = {a:0,b:{c:0}}
var obj2 = Object.assign({},obj1)

注意:当对象中只有一级属性,没有二级属性,此方法为深拷贝,但是对象中有对象时,此方法在二级属性后为浅拷贝。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值