This is the 12th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021
In this series of interviews, you’ll learn how to copy in JavaScript and how to write deep and light copies by hand.
If you feel helpful, please click 👍 to encourage you
What is copy
Copy is actually replication. In many scenarios, we need to copy a copy of data, and then operate the copied data, which may not affect the original data, or may require some linkage with the original data. Therefore, according to the functions of deep copy and shallow copy, the two requirements can be met.
A copy of the value type
There is no such thing as a deep copy of a value type. Because the copied value type does not correlate with the original data, changing the copied value does not change the original data.
let a = 1
let b = a
b = 2
console.log(a) / / = > 1
console.log(b) / / = > 2
Copy the code
Shallow copy
When memory is re-created in the heap, the base types before and after the copy do not affect each other, and the reference types before and after the copy still share the same memory, so they affect each other.
Here’s an example:
// Define a shallow copy function
function shallowCopy(obj) {
const cloneObj = {}
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
cloneObj[i] = obj[i]
}
}
return cloneObj
}
/ / declare the person
let person = {
name: "Zhang".hobbies: ["Eat"."Sleep"."Beat the beans."]}// Make a shallow copy of person to get person1
let person1 = shallowCopy(person)
// Change the value type
person1.name = 'bill'
// Change the reference type
person1.hobbies[0] = 'beauty'
console.log(person);
console.log(person1);
Copy the code
As you can see, when we change the person1 value type attribute name, it doesn’t affect the Person name, but when we change the reference type hobbies, the Person changes with person1, which is a shallow copy.
In addition to the above, shallow copy implementations include object.assign (), the expansion operator… ., array slice () array concat ().
Deep copy
Create a new area of heap memory to store the new object, make a recursive copy of all attributes of the original object, and also create a new area for all attributes of reference type, modify the new object does not affect the original object.
From the shallow copy example above, we can see that the person’s hobbies is a reference type, but each element of the hobbies is a string, that is, a value type, so the hobbies will not affect each other as long as we shallow copy the hobbies again. So we can conclude that if we make a shallow copy of an object recursively, the end result is a deep copy.
Recursive shallow copy
The code is as follows, allowing for special cases.
// Define a deep-copy function
function deepClone(obj) {
const cloneObj = new obj.constructor()
if (obj === null) return obj
if (obj instanceof Date) return new Date(obj)
if (obj instanceof RegExp) return new RegExp(obj)
if (typeofobj ! = ='object') return obj
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
cloneObj[i] = deepClone(obj[i])
}
}
return cloneObj
}
/ / declare the person
let person = {
name: "Zhang".hobbies: ["Eat"."Sleep"."Beat the beans."]}// Make a shallow copy of person to get person1
let person1 = deepClone(person)
// Change the value type
person1.name = 'bill'
// Change the reference type
person1.hobbies[0] = 'beauty'
console.log(person);
console.log(person1);
Copy the code
The result is as follows, only Li Si likes beautiful women now. That means our deep copy is successful.
JSON.parse(JSON.stringify())
Parse (json.stringify ()) in addition to implementing deep copy recursively in the shallow copy way above, you can use json.parse (json.stringify ()) to achieve the same result.
But this approach has its drawbacks. Let’s take a look
/ / declare the person
let person = {
name: "Zhang".hobbies: ["Eat"."Sleep"."Beat the beans."].date: new Date.fuc: () = >{},reg: /w/
}
// Make a shallow copy of person to get person1
const person1 = JSON.parse(JSON.stringify(person));
// Change the value type
person1.name = 'bill'
// Change the reference type
person1.hobbies[0] = 'beauty'
console.log(person);
console.log(person1);
Copy the code
As a result, the date property changes from an object to a string, the FUc property disappears, and the reg property becomes an empty object. So this way is very bad, not careful there will be accidents.
undefined
, any function andsymbol
Value is ignored during serialization;Date
Dates are treated as strings;NaN
和Infinity
The value of the format andnull
Will be regarded asnull
;- Other types of objects, including
Map/Set/WeakMap/WeakSet
, only enumerable attributes are serialized; - Executing this method on objects that contain circular references (objects that refer to each other in an infinite loop) throws an error;
Let’s use the recursive shallow-copy method to see the result, which is exactly the same.