This is the sixth day of my participation in the August More text Challenge. For details, see:August is more challenging
Deep copy and shallow copy
Shallow copy:
Creates a new object that has all the property values of the original object. If the property is of a primitive type, the value of the primitive type is copied; if the property is of a reference type, the memory address is copied. When a property of one object changes, the other object is also affected.
Here’s a shallow copy method:
function shallowClone(target) {
let cloneTarget = {};
for (const key in target) {
cloneTarget[key] = target[key];
}
return cloneTarget;
};
Copy the code
Deep copy:
A deep copy is a complete copy of an object from memory, creating a new space in the heap for the new object, so that modifying one object does not affect the other.
The deep copy method
1.JSON.parse(JSON.stringify());
In ordinary work, we often use deep copy methods, we use the most is the following method.
JSON.parse(JSON.stringify());
Copy the code
This is a very simple way to write it, and it’s very common to use it, and it does implement deep copies of objects, and it works for most scenarios, but it has a lot of drawbacks. Such as:
-
Ignores undefined
-
Ignore the symbol
-
Uncopyable function
-
Objects with circular references cannot be resolved
Consider the following example:
let a = {
age: undefined.sex: Symbol('male'),
jobs: function() {},
name: 'jack'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "jack"}
Copy the code
In the above case, the deep copy method ignores functions, undefined, and symbol, which is a problem.
2. $.extend()
$.extend() can also be used in jQuery.
let obj = {
a:1.b:2.c: {
x: 0.y: 1}};let cloneObj = $.extend(true, {}, obj);
obj.c.x = Awesome!;
console.log(cloneObj);
Copy the code
$.extend() = $.extend() = $.extend() = $.extend() = $.extend();
This section describes how to manually implement deep copy
The principle of a deep copy is simple. We simply create a new object and then add the properties of the original object to the new object in turn, directly to the new object if it is a primitive type, and recursively until the properties are of the primitive type if it is a reference type. So we can implement a simple deep copy method:
function _deepClone(target) {
if (typeof target === 'object') {
let cloneTarget = Array.isArray(target) ? [] : {};
for(key in target) {
cloneTarget[key] = _deepClone(target[key]);
}
return cloneTarget
} else {
return target
}
}
Copy the code
However, this still has the problem of circular references, such as the following example:
const target = {
field1: 1.field2: undefined.field3: {
child: 'child'
},
field4: [2.4.8]}; target.target = target;let res = _deepClone(target);
console.log(res);
Copy the code
When we execute the above code, the console will throw an error: Uncaught RangeError: Maximum Call stack size exceeded, because the above object has a circular reference, that is, an object whose properties indirectly or directly refer to themselves.
To solve the problem of circular reference, we can open up a extra storage space, to store the current objects and copy the object correspondence, when need to copy the current object, go to the storage space, find ever copy this object, if any direct return, if not to copy, so clever resolve the problems of the circular reference.
function _deepClone(target, map = new Map(a)) {
if (typeof target === 'object') {
let cloneTarget = Array.isArray(target) ? [] : {};
if (map.get(target)) {
return map.get(target);
}
map.set(target, cloneTarget);
for (const key in target) {
cloneTarget[key] = _deepClone(target[key], map);
}
return cloneTarget;
} else {
returntarget; }};Copy the code
Here to achieve deep copy method is just a simple copy, actually achieve a truly deep copy is very difficult, we need to consider a variety of situations, such as the prototype chain how to deal with, how to deal with the DOM, functions, how to deal with, and so on, because my level is limited now only understand here, deep copy of the follow-up will gradually achieve a more complete method.