关于浅拷贝深拷贝那些事儿

概念

浅拷贝:拷贝的只是对象的(引用)地址,新旧对象还是共享同一块内存,修改新对象会影响到原始对象数值发生变化

深拷贝:完全复制一个对象出来,新旧对象不共享内存,修改新对象不会改变原对象

浅拷贝

直接赋值
  • 任何操作都会影响原数组
let arr = [1, 2, 3, 4]
let newArr = arr
newArr.push(5, 6, 7)
console.log('newArr:', newArr) // [1, 2, 3, 4, 5, 6, 7]
console.log('arr:', arr) // [1, 2, 3, 4, 5, 6, 7]
Object.assign()
  • 拷贝属性值,假如属性值是一个对象的引用,那么也会指向那个引用
let obj = {
	id: 1,
	name: 'karim',
	msg: {
		age: 18
	}
};
let newObj = {};
Object.assign(newObj, obj);
// 修改拷贝后的对象中某一个值后,原来的对象也会改变
newObj.msg.age = 20;
console.log('拷贝后新对象:', newObj.msg.age) // 拷贝后新对象: 20
console.log('原对象:', obj.msg.age) // 原对象: 20
Array.prototype.concat()

注意:如果数组中都是简单数据类型,可以作为深拷贝使用

let arr = [1, 2, 3, 4, 5]
let newArr = [].concat(...arr)
newArr.push(6)
console.log('newArr', newArr) // [1, 2, 3, 4, 5, 6]
console.log('arr', arr) // [1, 2, 3, 4, 5]
实现浅拷贝
let arr = [1, 2, 3, { obj: 'karim' }]
let newArr = [].concat(...arr)
console.log('newArr', newArr[3]) // {obj: "xiaoming"}
newArr[3].obj = 'xiaoming'
console.log('arr', arr[3]) // {obj: "xiaoming"}
Array.prototype.slice()

concat()方法同理,简单类型可以作为深拷贝

let arr = [1, 2, 3, 4, 5]
let newArr = arr.slice(0, 5)
console.log('newArr', newArr) // [1, 2, 3, 4, 5]
newArr.push(7)
console.log('arr', arr) // [1, 2, 3, 4, 5, 7]
实现浅拷贝
let arr = [{ a: '123' }, { b: '456' }]
let newArr = arr.slice(0, 2)
console.log('newArr', newArr) // 0: {a: "123"} 1: {b: "789"}
newArr[1].b = '789'
console.log('arr', arr) // 0: {a: "123"} 1: {b: "789"}
使用扩展运算符
let arr = [{ a: '123' }, { b: '456' }]
let newArr = [...arr]
newArr[0].a = '789'
console.log('newArr', newArr[0].a) // newArr 789
console.log('arr', arr[0].a) // arr 789
通过for..in循环进行对象的遍历
let obj = {
	id: 1,
	name: 'karim',
	msg: {
		age: 18
	}
};

let newObj = {};
for (let k in obj) {
  /*	console.log('对象的值为:', obj[k])*/
	newObj[k] = obj[k];
}
// 修改拷贝后的对象中某一个值后,原来的对象也会改变
newObj.msg.age = 20
console.log('拷贝后新对象:', newObj.msg.age); // 拷贝后新对象: 20
console.log('原对象:', obj.msg.age) // 原对象 20

实现浅拷贝的方式不仅局限于上面的几种还可以用jQuery中的$.extend()函数,Lodash工具库的clone方法,都可以实现,可以自行To learn on their own下。

深拷贝

手动复制对象
  • 完全的copy一个新对象出来
let obj = {
	a: '123',
	b: '234'
}
let newObj = {
	a: obj.a,
	b: obj.b
}
newObj.a = '456'
console.log('newObj', newObj)// {a: "456", b: "234"}
console.log('obj', obj) // {a: "123", b: "234"}
使用JSON.parse(JSON.stringify(obj))

用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象,这个拷贝需要注意的是不能拷贝函数,因为JSON格式字符串不支持Function,在序列化的时候会自动删除

let obj = {
	a: '123',
	b: '234'
}
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj) // {a: "123", b: "234"}
newObj.a = '456'
console.log(obj) // {a: "123", b: "234"}

使用递归的方式

let obj = {
	id: 1,
	name: 'karim',
	msg: {
		age: 18
	},
	habits: ['reading', 'coding', 'playGames']
};
let newObj = {};
function deepCopy(newObj, obj) {
	// 遍历对象
	for (let k in obj) {
		// 将属性值赋值到item变量中
		let item = obj[k];
		// 判断值是否是数组
		if (item instanceof Array) {
			newObj[k] = [];
			deepCopy(newObj[k], item);
		} else if (item instanceof Object) { // 判断是否是对象
			newObj[k] = {};
			deepCopy(newObj[k], item)
		} else { // 是否是简单数据类型
			newObj[k] = item;
		}
	}
	// 返回深拷贝后的对象
	return newObj
}
deepCopy(newObj, obj);
newObj.msg.age = 21;
console.log(newObj.msg.age); // 21
console.log(obj.msg.age);  // 18

其他方法大家可以自行摸索下,比如lodash_.cloneDeep()等等。

参考资料:

js深拷贝和浅拷贝及其实现方式

深拷贝的实现方式

如何写出一个惊艳面试官的深拷贝?

End~

个人博客已上线,欢迎来访~
传送门:夜雨炊烟

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜雨炊烟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值