深浅拷贝
1、什么是深浅拷贝
深浅拷贝都只是针对引用对象来区分的,其他基本类型并不区分什么深浅拷贝。
浅拷贝:
浅拷贝是对内存地址的复制,让目标对象指针和源对象指向同一片内存地址。
当内存销毁的时候,指向对象的指针必须重新定义才能够使用。
深拷贝:
深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后两个对象虽然存的值是一样的,但是内存地址不一样。
2、深浅拷贝的实现
- 浅拷贝实现方式
1、方式一:直接赋值即可实现对象浅拷贝
// 浅拷贝
let obj1 = { a: 0, b: { c: 0 } }
let obj2 = obj1
console.log(obj1); // { a: 0, b: { c: 0 } }
console.log(obj2); // { a: 0, b: { c: 0 } }
console.log(obj1 === obj2); // true
// 修改obj1中的a属性
obj1.a = 1
// 可以看到obj2中的a属性的值也改变了,这样就能证明obj2只是对obj1对象内存地址的复制,指针还是指向obj1对象内存地址
console.log(obj2); // { a: 1, b: { c: 0 } }
2、方式二:解决赋值
let obj1 = {info:{name:"nick", age:23}}
// 通过展开元素符进行浅复制
let {info} = obj1
3、其他的数组的一些方法,例如 Array.property.slice() 以及 Array.property.concat() 也可以实现浅拷贝
4、自定义浅拷贝:
function shallowCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
let copy = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = obj[key];
}
}
return copy;
}
- 深拷贝实现方式:
方式一:JSON.stringify()方法和JSON.parse()方法实现
let obj1 = {a:0,b:{c:"hello"}}
let obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2); // { a: 0, b: { c: 'hello' } }
obj1.a = 1
console.log(obj1); // { a: 1, b: { c: 'hello' } }
console.log(obj2); // { a: 0, b: { c: 'hello' } }
// 可以看到,obj1的a属性取值改变并不会影响到obj2中的a属性取值,
// 所以也就可以说明这两个对象内存地址并不一样
需要注意的是,JSON.stringify() 和 JSON.parse() 方法只能处理支持 JSON 格式的数据类型,包括对象、数组、字符串、数字、布尔值和 null。它们无法处理特殊类型(如函数、symble、正则表达式、日期)以及循环引用等情况。
方式二:通过assign()方法实现(特殊)
关于assign()方法的介绍可以看MDN官方
这个方法比较特殊,当对象嵌套层次小于2层,则是深拷贝,大于等于2层时则是浅拷贝,具体原理:利用拼接原理,对对象进行拼接,将后续对象的内容插入到第一个参数指定的对象,并且不会修改第一个参数之后的对象。
let obj1 = { a: 0, b: { c: "hello" } }
let obj2 = Object.assign({}, obj1)
obj1.a = 1 // 小于2层的为深拷贝
obj1.b.c = '你好' // 大于等于层的为浅拷贝
console.log(obj1); // { a: 1, b: { c: '你好' } }
console.log(obj2); // { a: 0, b: { c: '你好' } }
方式三:自定义深拷贝(递归实现)
function deepCopy(source) {
if (source === null || typeof source !== 'object' || source instanceof Date || source instanceof RegExp) {
return source;
}
let copy = Array.isArray(source) ? [] : {}
for (let key in source) {
if (source.hasOwnProperty(key)) {
copy[key] = deepCopy(source[key]);
}
}
return copy;
}