I. understanding
Shallow copy only copies the pointer to an object, not the object itself. The new and old objects still share the same block of memory. But deep copy will create another object that is exactly the same. The new object does not share memory with the original object, and the new object will not be changed to the original object.
Shallow copy and deep copy
-
Shallow copy: when assigning a value, the basic data type is passed by value, and the object is passed by reference
var a = 25; var b = a; b = 18; console.log(a);//25 console.log(b);//18 // b's modification does not affect a, because they are basic type data
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = obj1; obj2.b = 100; console.log(obj1); // {A: 10, B: 100, C: 30} < -- B was changed to console.log(obj2); // { a: 10, b: 100, c: 30 } // Obj 2 modifies the value of b, and obj 1's b will also be modified, because they are the same object, which is called shallow copy
-
Deep copy:
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c }; obj2.b = 100; console.log(obj1); // {A: 10, B: 20, C: 30} < -- B has not been changed to console.log(obj2); // { a: 10, b: 100, c: 30 }
III. implementation mode
-
Implementation of shallow copy
(1) direct assignment is shallow copy. If the object is copied directly, the changes of the new object will also be modified to the old object.
(2) Object.assign(target, ...sources)Object.assign
yesES6
New function for.Object.assign()
Method can copy the enumerable properties of any multiple source objects to the target object, and then return to the target object. howeverObject.assign()
Shallow copy is performed, and attribute value is copied. If the property value of the source object is a reference to the object, it only copies that reference value.var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
(3) object expansion
var obj = [{index: 1, msg: 'one'}, {index: 2, msg: 'two'}]; var obj2 = [...obj]; console.log(obj2); //[{index: 1, msg: 'one'}, {index: 2, msg: 'two'}] obj2.push({index: 3, msg: 'three'}); console.log(obj2); // [{index: 1, msg: 'one'}, {index: 2, msg: 'two'}, {index: 3, msg: 'three'}] console.log(obj); // [{index: 1, msg: 'one'}, {index: 2, msg: 'two'}] obj2[1].msg = 'two again'; console.log(obj2); // [{index: 1, msg: 'one'}, {index: 2, msg: 'two again'}, {index: 3, msg: 'three'}] console.log(obj); // [{index: 1, msg: 'one'}, {index: 2, msg: 'two again'}]
-
Implementation of deep copy
(1) manual copyvar obj1 = { a: 10, b: 20, c: 30 }; var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };
(2) convert to JSON and then switch back (only objects that can be converted to JSON format can be used in this way, like function, which can't be converted to JSON)
var obj1 = { body: { a: 10 } }; var obj2 = JSON.parse(JSON.stringify(obj1)); obj2.body.a = 20; console.log(obj1); // {body: {A: 10}} < -- not changed to console.log(obj2); // { body: { a: 20 } } console.log(obj1 === obj2); // false console.log(obj1.body === obj2.body); // false
(3) use var newObj = Object.create(oldObj) method
function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // Avoid dead loops caused by cross referencing objects, such as initalObj.a = initalObj if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : Object.create(prop); } else { obj[i] = prop; } } return obj; } var str = {}; var obj = { a: {a: "hello", b: 21} }; deepClone(obj, str);