Deep copy and shallow copy

Deep copy and shallow copy, like B copies A, and when YOU modify A, see if B changes,

  • If B changes, it’s a shallow copy
  • If B doesn’t change, it’s a deep copy

Basic, reference data type data, stack heap


The data type

Basic data types:

  • number.string.boolean.null.undefined.symbolAnd BigInt(arbitrary precision integer) class 7 added to ES10 in the future

Reference data types (class Object):

  • Unordered objects {a:1} with regular name-value pairs, arrays, and functions

Data storage mode

Basic types of

Names and values are stored in stack memory

For example, let a=1;

When b=a is assigned, a new stack memory is created:

So when you change a=2, it doesn’t affect B. But this is not really deep copy either, because deep copy itself is only for more complex Object type data.


Reference data type

The name is in stack memory, the value is in heap memory, and the stack memory provides a referenced address to the value in heap memory

When b=a is copied, it is actually copying the reference address of A, not the value in the heap.

When a[0]=1, we modify the array, because a and B point to the same address, so naturally B is affected, this is called shallow copy.

If you create a new memory in the heap for b, just like the base type, you can achieve the effect of deep copy.


Implement simple deep copy


The recursive implementation

Principle: Recursively copy all hierarchical attributes

Example:

function deepClone(obj){
    let objClone = Array.isArray(obj)? [] : {};if(obj && typeof obj==="object") {for(key in obj){
            if(obj.hasOwnProperty(key)){
                // Determine whether the oJB child is an object, if so, recursively copy
                if(obj[key]&&typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    // If not, simply copyobjClone[key] = obj[key]; }}}}return objClone;
}    

let a=[1.2.3.4],
b=deepClone(a);
a[0] =2;
console.log(a,b); //[2, 2, 3, 4] [1, 2, 3, 4]
Copy the code

JSON. Stringfy () and JSON. The parse ()

let cloneObj=JSON.parse(JSON.stringify(obj));
Copy the code

Principle:

Use json.stringify to serialize the JS object (JSON string) and use json.parse to deserialize (restore) the JS object.

The purpose of serialization is to store (the object itself stores only an address map, if the power is turned off, the object will not exist, Therefore, it is necessary to convert the Content of objects into strings and save them on disk) and transfer (for example, if the content-type of the request is Application/X-www-form-urlencoded, The front end needs to use Qs.stringify (data) to serialize parameters and then pass them to the back end, otherwise the back end cannot accept them. Ps: the content-type for application/json; Charset =UTF-8 or multipart/form-data is not required.

Example:

function deepClone(obj){
    let _obj = JSON.stringify(obj),
        objClone = JSON.parse(_obj);
    return objClone
}    

let a=[0.1[2.3].4],
b=deepClone(a);
a[0] =1;
a[2] [0] =1;
console.log(a,b);
Copy the code

Note: This crude approach has its limitations:


limitations
  1. If obj has a time object in it, json.stringify will be followed by json.parse, and the time will be just a string. Instead of a time object:
var test = {
    name: 'a'.date: [new Date(1536627600000), new Date(1540047600000)]};let b;
b = JSON.parse(JSON.stringify(test))
console.log(b)
Copy the code

  1. If there are RegExp and Error objects in obj, the serialized result will be empty:
const test = {
     name: 'a'.date: new RegExp('\\w+'),};const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'
console.error('ddd', test, copyed)
Copy the code

  1. If obj has a function called undefined, then the serialization result will lose the function or undefined:
const test = {
    name: 'a'.date: function hehe() {
        console.log('fff')}};const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'
console.error('ddd', test, copyed)
Copy the code

Undefined as lost:

  1. If obj contains NaN, Infinity, and ** -infinity **, then the serialized result will be null:

  1. Json.stringify () serializes only the enumerable properties of the object itself, for example if the object in obj is generated by a constructor, the constructor of the object is discarded after using a deep copy of json.parse (json.stringify (obj)) :
function Person(name) {
    this.name = name;
    console.log(name)
}
const liai = new Person('liai');	
const test = {
  name: 'a'.date: liai,
};
const copyed = JSON.parse(JSON.stringify(test));
test.name = 'test'
console.error('ddd', test, copyed)
Copy the code

  1. Deep copy cannot be correctly implemented if there are circular references in the object.

Parse (json.stringify (obj)) can be used to implement deep copy if the copied object does not cover the above situations. But in the case above, consider using the recursive implementation above.

Read about json.stringify ==> what you don’t know about the power of json.stringify ()


Deep copy is not just for interview questions, it can be very useful in practical development. A pile of data received from the background, for example, you need to do to the heap data operation, but many people development situation, you are unable to clear this heap data to see if there is other functions also need to use, modify directly may lead to hidden problem, a deep copy can help you more safe and comfortable to manipulate data, according to the actual situation to use deep copy.


Deep copy of one layer/multiple layers of objects/arrays

Deep copy with multiple nested layers

See above – implementing simple deep copy


A deep copy of an array or object


Slice () – A deep copy of the array
var arr = [1.2.3]
var newArr = arr.slice()
arr.push(4)
console.log(arr) // [1, 2, 3, 4]
console.log(newArr) / / [1, 2, 3]
Copy the code

Concat () – Deep copy of a layer array
var arr = [1.2.3]
var newArr = arr.concat()
arr.push(4)
console.log(arr) // [1, 2, 3, 4]
console.log(newArr) / / [1, 2, 3]
Copy the code

Destruct assignment – a deep copy of a layer of arrays/objects
/ / array
var arr = [1.2.3]
var newArr = [...arr]
arr.push(4)
console.log(arr) // [1, 2, 3, 4]
console.log(newArr) / / [1, 2, 3]
/ / object
var obj = { name: 'winne' }
varnewObj = { ... obj } obj.name ='xf'
console.log(obj) // {name: "xf"}
console.log(newObj) // {name: "winne"}
Copy the code

Object.assign() – A deep copy of a layer of objects
var obj = { name: 'winne' }
var newObj = Object.assign({}, obj)
obj.age = 20
console.log(obj) // {name: "winne", age: 20}
console.log(newObj) // {name: "winne"}
Copy the code

Filter () – Deep copy of a layer array
var arr = [1.2]
var newArr = arr.filter((item) = > {
  return true
})
arr.push(88)
console.log(arr) / / [1, 2, 88]
console.log(newArr) / / [1, 2]
Copy the code

Map () – A deep copy of an array
var arr = [1.2]
var newArr = arr.map((item) = > {
  return item
})
arr.push(88)
console.log(arr) / / [1, 2, 88]
console.log(newArr) / / [1, 2]
Copy the code