JS深拷贝实现记录

一、实现深拷贝之前,我们要先搞明白深拷贝的定义是什么?

在JavaScript中,数据类型分为基本数据类型和引用数据类型两种,对于基本数据类型来说,它的值直接存储在栈内存中,而对于引用类型来说,它在栈内存中仅仅存储了一个引用,而真正的数据存储在堆内存中

因此,在进行赋值操作时,会因为不同的类型产生不同的效果,简单举例一下。

基本类型:

let a = 1, b = a;
b = 2
console.log(a);//1
console.log(b);//2

引用类型:

let obj = {
    a:1,
    b:2
},
obj2 = obj;

obj2.a = 11;

console.log(obj.a); //11
console.log(obj1.a); //11

显然,两个对象的值都被修改了。

当值是引用类型时,修改obj2内部的属性值会导致obj的值也被修改。我们其实仅仅只是将 obj1 存储在栈堆中的的引用赋予了 obj2 ,而两个对象此时指向的是在堆内存中的同一个数据,所以当我们修改任意一个值的时候,修改的都是堆内存中的数据,而不是引用,所以只要修改了,同样引用的对象的值也自然而然的发生了改变

 

 

二、进入主题,深拷贝的实现

1、浅拷贝

先来看看浅拷贝的实现

let obj = {
    a: 1,
    b: 2
}
let obj2 = Object.assign({}, obj1);

Object.assign的拷贝,是对于第一层属性的拷贝,所以是浅拷贝。

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

2、深拷贝

第一种:乞丐版深拷贝

let obj = {
    a: 1,
    b: 2,
    c: 3
}
let obj2 = JSON.parse(JSON.stringify(obj));
obj2.a = 5;
console.log(obj.a);  // 1
console.log(obj2.a); // 5

第二种:

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

上面两种方式对于只有简单属性的对象而言,可以实现深拷贝,但是对象的属性也为对象时就无能为力

第三种:最终版

function deepClone(obj){
	let cloneObj;
	if(typeof obj === 'object'){
        if(obj === null){
		 //若为null,直接赋值
        	cloneObj = null
        }else if(obj instanceof Date){
			 //Date类型
			cloneObj = new Date(obj)
		}else if(obj instanceof RegExp){
			 //RegExp类型
			cloneObj = RegExp(obj)
		}else if(Array.isArray(obj)){
			 //Array类型
			cloneObj = []
			for(let key in obj){
				cloneObj.push(arguments.callee(obj[key]))
			}
		}else{
			 //Object类型
			cloneObj = {}
			for(let key in obj){
				cloneObj[key] = arguments.callee(obj[key])
			}
		}
	}else{
        //否则为基本类型
		cloneObj = obj
	}
	return cloneObj
}


var obj = {
	func:deepClone,
	arr:[1,2,3,{a:{b:1}}],
	obj:{
		name:'obj.obj',
		age:23
	},
	str:'11',
	date:new Date(),
	reg:new RegExp()
} 
let obj2 = deepClone(obj)

obj2.obj.name = 'obj2.obj'
console.log('obj:',obj.obj.name);//obj: obj.obj
console.log('obj2:',obj2.obj.name);//obj2: obj2.obj

特别注意,在拷贝函数中,需要判断是否为特别对象类型(Date、RegExp等),需要重新创建再赋值。数组也需要创建空数组再进行操作。

OK,以上就是深拷贝的实现方法。


本人菜鸟一枚,本帖仅为学习之余记录贴,如有错误的地方望不吝赐教。

最后,感谢您的阅读!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值