Javascript深浅拷贝问题

本文最后更新于:2021年1月18日 晚上

想要实现这样一个功能:

进入添加数据页面,想添加一些数据,可是写到一半想退出添加数据页面,这时候数据需要回退为之前的旧数据

代码逻辑如下:

# 原数据
let info = {
	name: "Mike",
	age: 15
}

# 更改
# 1.保存旧数据
let history = info
# 2.更改新数据
let info = {
	name: "new name",
	age: "new age"
}
# 3.退出,将数据指向history
let info = history

# 输出现在的数据
console.log(info)  # {name:"new name",age:"new age"}

这时候会发现这样的问题:

即使在更改数据前,将旧数据(info)指向一个中间变量(history),在更改旧数据(info)后,这个中间变量(history)也跟随改变了,并没有起到保存的作用

问题的原因

经过上面这么长的铺垫,终于可以进入我们的正题,也是出现上面问题的原因:

javascript变量

javascript的变量有两种:
1.原始值:简单的数据,按值访问
2.引用值:多个数据构成的对象,按引用访问

复制原始值时,就是将值复制一份,例如:

let a = 123
let b = a
console.log(a,b) # 123,123

原始值复制

复制引用值时,是将值的引用指向新的变量,数据堆中并没有新的数据出现,例如:

let a = {
	name: 123,
	age: 456
}
let b = a
console.log(a,b) #{name: 123, age: 456},{name: 123, age: 456}
a.name = 789
console.log(a,b) #{name: 789, age: 456},{name: 789, age: 456}

因为更改的都是数据堆里的值,所以指向该对象的变量数据都会随之改变
引用值复制

解决办法

这里我们可以使用深拷贝的方法来改变引用值的复制,原理如下:
将对象转换为json字符串形式(String类型在Javascript中是原始值),再将该值赋值给新变量,再将该变量转换为原生js对象

deepClone(obj){
	let _tmp = JSON.stringify(obj); //将对象转换为json字符串形式
	let result = JSON.parse(_tmp); //将转换而来的字符串转换为原生js对象
	return result;
}
let a = {
	name: 123,
	age: 456
}
let b = deepClone(a)
console.log(a,b) #{name: 123, age: 456},{name: 123, age: 456}
a.name = 789
console.log(a,b) #{name: 789, age: 456},{name: 123, age: 456}

深拷贝的方法还有很多,这个是比较投机取巧的方法,使用这样的办法,可以在数据堆中新增一个Object,解决上面问题,不过在数据量较大时,容易发生栈溢出,不过在数据量较小时,推荐使用


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!