1, Data type storage
There are two data types in JavaScript:
-
Basic type
-
reference type
The basic type data is saved in stack memory
Reference type data is stored in heap memory. The variable of reference data type is a reference to the actual object in heap memory and exists in the stack
2, Shallow copy
Shallow copy refers to the creation of new data, which has an accurate copy of the attribute value of the original data
If the attribute is a base type, the value of the base type is copied. If the attribute is a reference type, the memory address is copied
That is, a shallow copy is a copy layer, and a deep reference type is a shared memory address
Here's a simple implementation of a shallow copy
function shallowClone(obj) { const newObj = {}; for(let prop in obj) { if(obj.hasOwnProperty(prop)){ newObj[prop] = obj[prop]; } } return newObj; }
In JavaScript, there are shallow copies:
-
Object.assign
-
Array.prototype.slice(), Array.prototype.concat()
-
Replication using extension operators
Object.assign
var obj = { age: 18, nature: ['smart', 'good'], names: { name1: 'fx', name2: 'xka' }, love: function () { console.log('fx is a great girl') } } var newObj = Object.assign({}, fxObj);
slice()
const fxArr = ["One", "Two", "Three"] const fxArrs = fxArr.slice(0) fxArrs[1] = "love"; console.log(fxArr) // ["One", "Two", "Three"] console.log(fxArrs) // ["One", "love", "Three"]
concat()
const fxArr = ["One", "Two", "Three"] const fxArrs = fxArr.concat() fxArrs[1] = "love"; console.log(fxArr) // ["One", "Two", "Three"] console.log(fxArrs) // ["One", "love", "Three"]
Extension operator
const fxArr = ["One", "Two", "Three"] const fxArrs = [...fxArr] fxArrs[1] = "love"; console.log(fxArr) // ["One", "Two", "Three"] console.log(fxArrs) // ["One", "love", "Three"]
3, Deep copy
Deep copy opens up a new stack. The properties of two objects are the same, but corresponding to two different addresses. Modifying the properties of one object will not change the properties of the other object
Common deep copy methods include:
-
_.cloneDeep()
-
Handwriting loop recursion
JSON.stringify()
const obj2=JSON.parse(JSON.stringify(obj1));
However, there are disadvantages in this method, which ignores undefined, symbol and functions
const obj = { name: 'A', name1: undefined, name3: function() {}, name4: Symbol('A') } const obj2 = JSON.parse(JSON.stringify(obj)); console.log(obj2); //
Circular recursion
function deepClone(obj, hash = new WeakMap()) { if (obj === null) return obj; // If it is null or undefined, I will not copy if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); // It could be an object or a normal value If it's a function, you don't need a deep copy if (typeof obj !== "object") return obj; // If it is an object, you need to make a deep copy if (hash.get(obj)) return hash.get(obj); let cloneObj = new obj.constructor(); // The constructor on the prototype of the class is found, and the constructor on the prototype is not found The constructor points to the current class itself hash.set(obj, cloneObj); for (let key in obj) { if (obj.hasOwnProperty(key)) { // Implement a recursive copy cloneObj[key] = deepClone(obj[key], hash); } } return cloneObj; }
4, Distinction
First of all, with the help of two figures, you can see the difference between shallow copy and deep copy more clearly
It is found from the above figure that both shallow copy and deep copy create a new object, but the behavior is different when copying object attributes
Shallow copy only copies the pointer of the attribute to an object, not the object itself. The old and new objects still share the same block of memory. Modifying the object attribute will affect the original object
// Shallow copy const obj1 = { name : 'init', arr : [1,[2,3],4], }; const obj3=shallowClone(obj1) // A shallow copy method obj3.name = "update"; obj3.arr[1] = [5,6,7] ; // Old and new objects still share the same block of memory console.log('obj1',obj1) // obj1 { name: 'init', arr: [ 1, [ 5, 6, 7 ], 4 ] } console.log('obj3',obj3) // obj3 { name: 'update', arr: [ 1, [ 5, 6, 7 ], 4 ] }
But deep copy as like as two peas will create another object that is exactly the same. New objects do not share memory with original objects.
// Deep copy const obj1 = { name : 'init', arr : [1,[2,3],4], }; const obj4=deepClone(obj1) // A deep copy method obj4.name = "update"; obj4.arr[1] = [5,6,7] ; // The new object does not share memory with the original object console.log('obj1',obj1) // obj1 { name: 'init', arr: [ 1, [ 2, 3 ], 4 ] } console.log('obj4',obj4) // obj4 { name: 'update', arr: [ 1, [ 5, 6, 7 ], 4 ] }
Summary
If the copy type is reference type:
-
Shallow copy is a copy layer. When the attribute is an object, shallow copy is a copy, and the two objects point to the same address
-
Deep copy is a recursive deep copy. When the attribute is an object, deep copy is a new stack, and the two objects point to different addresses