There are two main data types in JavaScript:
- Basic type Number String NULL Undefined Boolean symbol
- Reference type Array Object function
Basic type data is stored in stack memory
Reference type data is stored in heap memory, and the variable of a reference data type is a reference to an actual object in heap memory, which is stored on the stack
Shallow copy
Shallow copy refers to the creation of new data that has an exact copy of the original data attribute values
If the property is of a primitive type, the value of the primitive type is copied. If the attribute is a reference type, the memory address is copied
That is, shallow copies copy a layer, and deep reference types share memory addresses
Let’s simply implement a shallow copy
function shallowClone(obj) {
const newObj = {};
for(let prop in obj) {
if(obj.hasOwnProperty(prop)){ newObj[prop] = obj[prop]; }}return newObj;
}
Copy the code
In JavaScript, shallow copies exist:
- Object.assign
- Array.prototype.slice(), Array.prototype.concat()
- Replication using extended 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);
Copy the code
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"]
Copy the code
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"]
Copy the code
Extended operator
const fxArr = ["One"."Two"."Three"]
const fxArrs = [...fxArr]
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
Copy the code
Deep copy
Deep copy opens up a new stack. Two object families are identical but correspond to two different addresses. Modifying the properties of one object does not change the properties of the other
Common deep-copy modes are:
- _.cloneDeep()
- jQuery.extend()
- JSON.stringify()
- Handwriting loop recursion
_.cloneDeep()
const _ = require('lodash');
const obj1 = {
a: 1.b: { f: { g: 1}},c: [1.2.3]};const obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);// false
Copy the code
jQuery.extend()
const$=require('jquery');
const obj1 = {
a: 1.b: { f: { g: 1}},c: [1.2.3]};const obj2 = $.extend(true, {}, obj1);
console.log(obj1.b.f === obj2.b.f); // false
Copy the code
JSON.stringify()
const obj2=JSON.parse(JSON.stringify(obj1));
Copy the code
However, this approach has the disadvantage of ignoring 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); // {name: "A"}
Copy the code
Cycle recursion
function deepClone(obj, hash = new WeakMap(a)) {
if (obj === null) return obj; // If it is null or undefined, I will not copy it
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// May be objects or ordinary values if functions do not need deep copies
if (typeofobj ! = ="object") return obj;
// Make a deep copy of an object
if (hash.get(obj)) return hash.get(obj);
let cloneObj = new obj.constructor();
// Find the constructor from the parent class stereotype, which points to the current class itself
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// Implement a recursive copycloneObj[key] = deepClone(obj[key], hash); }}return cloneObj;
}
Copy the code
Fourth, the difference between
Here are two images to help you see the difference between a shallow copy and a deep copy
As you can see from the above figure, both shallow and deep copies create a new object, but behave differently when copying object properties
Shallow copy only copies the pointer that the attribute points to an object, but not the object itself. The old and new objects still share the same memory. Modifying object attributes affects 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 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 ] }
Copy the code
But deep copy will create another identical object, the new object and the original object do not share memory, modify the new object will not change to the original object
/ / 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 ] }
Copy the code
summary
If the copy type is reference type:
- A shallow copy is a copy of a layer. If the property is an object, the shallow copy is a copy. The two objects point to the same address
- Deep copy is a deep recursive copy. If the property is an object, the deep copy is a new stack, and the two objects point to different addresses
Conclusion:
- Deep copy recursively copies all values or attributes in the new object, while copy copies only references.
- In a deep copy, changes in the new object do not affect the original object, while in a shallow copy, changes in the new object are changed in the original object.
- In the deep copy, the original object does not share the same properties as the new object, while in the shallow copy, they have the same properties.