先看看啥叫深拷贝?啥叫浅拷贝?
假设B复制了A,修改A的时候,看B是否发生变化:
如果B跟着也变了,说明是浅拷贝,拿人手短!(修改堆内存中的同一个值)
如果B没有改变,说明是深拷贝,自食其力!(修改堆内存中的不同的值)
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址
简单理解:
深拷贝(深复制):在计算机中开辟一块新的内存地址用于存放复制的对象。
浅拷贝(浅复制):仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
MDN Web开发文档上对Object.assign()得解释:
Object.assign()
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
官网示例:
const target = { a: 1, b: 2 }; const source = { b: 4, c: 5 }; const returnedTarget = Object.assign(target, source); console.log(target); // expected output: Object { a: 1, b: 4, c: 5 } console.log(returnedTarget); // expected output: Object { a: 1, b: 4, c: 5 }
语法: Object.assign(target, ...sources)
参数:target
目标对象、sources
源对象。
返回值:目标对象。
作用话根据官网来看:复制一个对象、拷贝对象(当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。)、合并对象。
描述:
如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性。
Object.assign
方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]
和目标对象的[[Set]]
,所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型,应使用Object.getOwnPropertyDescriptor()
和Object.defineProperty()
。
在出现错误的情况下,例如,如果属性不可写,会引发TypeError
,如果在引发错误之前添加了任何属性,则可以更改target
对象。
注意:Object.assign
不会在那些source
对象值为 null
或 undefined
的时候抛出错误。
Object.assign()对象的深拷贝
针对深拷贝,需要使用其他办法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用。 let obj1 = { a: 0 , b: { c: 0}}; let obj2 = Object.assign({}, obj1); console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} obj1.a = 1; console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}} console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} obj2.a = 2; console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}} console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}} obj2.b.c = 3; console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}} console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}} 最后一次赋值的时候,b是值是对象的引用,只要修改任意一个,其他的也会受影响 // Deep Clone (深拷贝) obj1 = { a: 0 , b: { c: 0}}; let obj3 = JSON.parse(JSON.stringify(obj1)); obj1.a = 4; obj1.b.c = 4; console.log(obj3); // { a: 0, b: { c: 0}}
递归的方式实现深拷贝
function _deepClone(source) { let target; if (typeof source === 'object') { target = Array.isArray(source) ? [] : {} for (let key in source) { if (source.hasOwnProperty(key)) { if (typeof source[key] !== 'object') { target[key] = source[key] } else { target[key] = _deepClone(source[key]) } } } } else { target = source } return target } const obj = { a: { aa: 1, aaa: 2 }, b: 2, c: 3 } var obj2 = _deepClone(obj) obj.b = 9 console.log(obj2) //{a: {aa: 1,aaa: 2}, b: 2, c: 3} console.log(obj) //{a: {aa: 1,aaa: 2}, b: 9, c: 3}
js实现深拷贝
const obj = { a: { aa: 1, aaa: 2 }, b: 2, c: 3 } let obj3 = JSON.parse(JSON.stringify(obj)); obj.a.aa = 4; obj.b = 9; console.log(obj3); // {a: {aa: 1,aaa: 2}, b: 2, c: 3} console.log(obj) // {a: {aa: 4,aaa: 2}, b: 9, c: 3}
本文参考: