在学习深拷贝之前,我们要先搞清楚js的数据类型,既:值类型引用类型 **值类型:**undefined, string, number, boolean, Symbol **引用类型:**object, function, array 对于基本数据类型来说,它的值直接存储在栈内存中,而对于引用类型来说,它在栈内存中仅仅存储了一个引用,而真正的数据存储在堆内存中 当我们对数据进行操作时,会发现两种情况:
// 值类型
let a1 = 10;
let b1 = a1;
a1 = 11;
console.log(b1); // 10
对于基本类型来说,我们将一具基本类型的值赋值给a1变量,接着将a1的值赋值给变量b1;然后修改a1,可以看到a1被修改了, b1的值并没有变化,两个变量都使用的独立的数据;
// 引用类型
let a2 = {a: 1};
let b2 = a2;
b2.a = 12;
console.log(a2.a); // 12
从结果可以看出两个对象的值全部被修改了 对于引用类型来说,我们将a2赋值给b2时,其实只是将a2的存储在堆中的引用地址赋值给b2,而两个对象此时指向的是在堆内存中的同一条数据,所以当我们修改做任意一个值 的时候,修改的都是堆内存中的数据,
js浅拷贝与深拷贝的区别 简单来说就是假设B复制了A对象,当修改A对象时,看B是否会发生变化,如果B也跟着变化了,说明是浅拷贝,如果B没有变化说明是深拷贝。
深拷贝实现 1.使用JSON.stringify()以及JSON.parse()
let o1 = {
a: 1,
b: 1
}
let o2 = JSON.parse(JSON.stringify(o1))
o2.a = 100
console.log(o1.a) // 1
// 缺点举例
let o1 = {
a: 1,
b: null,
c: false,
d: '123',
e: undefined,
f: function() {alert(123)},
g: /ss/
}
let o2 = JSON.parse(JSON.stringify(o1))
console.log(o2)
缺点:使用JSON.stringify()以及JSON.parse()它是不可以拷贝 undefined , function, RegExp等类型
2.使用Object.assign(target, source)
let o1 = {
a: 1,
b: null,
c: false,
d: '123',
e: undefined,
f: function() {alert(123)},
g: /ss/
}
let o2 = Object.assign({}, o1)
o2.a = 1000
console.log(o1.a) // 1
// 缺点举例
let o1 = {
a: 1,
b: null,
c: false,
d: '123',
e: undefined,
f: function() {alert(123)},
g: /ss/,
h: {
a: 1,
b: 2
}
}
let o2 = Object.assign({}, o1)
o2.h.a = 1000
console.log(o1.h.a)
缺点:对于一层对象来说是没有任何问题的,但是如果对象的属性对应的是其它的引用类型的话,还是只拷贝了引用,修改的话还是会有问题
3.递归拷贝
let o1 = {
a: 1,
b: null,
c: false,
d: '123',
e: undefined,
f: function() {alert(123)},
g: /ss/,
h: {
a: 1,
b: 2
}
}
function deepClone(obj = {}) {
if (typeof obj !== 'object') {
// obj不是对象情况直接返回
return obj;
}
// 初始化返回结果
let result
if (obj instanceof Array) {
result = []
} else {
result = {}
}
for (let key in obj) {
// 保证key不是原型的对象
if (obj.hasOwnProperty(key)) {
// 递归
if (obj[key] && typeof obj[key] === 'object' && obj[key].constructor !== RegExp) {
result[key] = deepClone(obj[key])
} else {
result[key] = obj[key]
}
}
}
// 返回结果
return result
}
let o2 = deepClone(o1)
o2.h.a = 123
console.log(o1.h.a) // 1