“This is the 17th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

1. Related knowledge points

1.1 Classification of basic types and Reference types

Basic types: number, string, Boolean, NULL, undefined, symbol and BigInt Reference types: objects, arrays, functions, etc.

1.2 Storage mode of variables in JS

Stack: automatically allocate memory space, automatically released by the system, which stores the name value of the basic type and the name (address) of the reference type;

Heap: dynamically allocated memory, of varying size and not automatically freed, that holds values of reference types;

1.2.1 Basic Types

Let a = 1;

When you copy b = a, the stack will create a new memory

When you change a=2, it doesn’t affect B;

let a=1,b=a;

B is not affected by A, but it’s not a deep copy. This is because deep copy itself is only for complex Object data.

1.2.2 Reference Data types

Let a = [0,1,2,3,4];

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

When a[0] = 1, the array is changed, because a and B point to the same address, so b is also affected, this is the shallow copy.

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

2. Method of shallow copy

2.1 For ···in circulates only the first layer

// Copy only the shallow copy of the first layer
function simpleCopy(obj1) {
  var obj2 = Array.isArray(obj1) ? [] : {};
  for (let i in obj1) {
   obj2[i] = obj1[i];
  }
  return obj2;
}
var obj1 = {
  a: 1.b: 2.c: {
    c1: 3}}var obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.c1 = 4;
console.log(obj1.a,obj2.a); // 1  3
console.log(obj1.c.c1,obj2.c.c1); // 4  4
Copy the code

2.2 the Object. The assign method

var obj1 = {
  a: 1.b: 2.c: {
    c1: 3}}var obj2 = Object.assign({},obj1);
obj2.a = 3;
obj2.c.c1 = 4
console.log(obj1.a,obj2.a) // 1  3
console.log(obj1.c.c1,obj2.c.c1); // 4  4
Copy the code

2.3 Assign directly with =

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

3. Methods to implement deep copy

3.1 Copy all level attributes recursively

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]
let b = deepClone(a);
a[0] =2;
console.log(a,b); / / (2, 2, 3, 4] [1, 2, 3, 4]
let obj1 = {
  a: 1.b: 2.c: {
    c1: 3}}let obj2 = deepClone(obj1)
obj2.c.c1 = 4
console.log(obj1,obj2); // {a:1,b:2,c:{c1:3}} {a:1,b:2,c:{c1:4}}
Copy the code

3.2 Using JSON Objects to Implement Deep Copy

Note: Deep copies of methods in objects cannot be implemented

function deepClone(obj) {
  var _obj = JSON.stringify(obj),
    objClone = JSON.parse(_obj);
  return objClone;
}  
let a = [1.2.3.4]
let b = deepClone(a);
a[0] =2;
console.log(a,b); / / (2, 2, 3, 4] [1, 2, 3, 4]
let obj1 = {
  a: 1.b: 2.c: {
    c1: 3.c2:function(){ // A deep copy of a method in an object cannot be implemented
      console.log('Deep copy')}}}let obj2 = deepClone(obj1)
obj2.c.c1 = 4
console.log(obj1,obj2); // {a:1,b:2,c:{c1:3,c2:f()}} {a:1,b:2,c:{c1:4}}
Copy the code

3.3 Use the extend method in jQuery to achieve deep copy

$.extend( [deep ], target, object1 [, objectN ] )

Deep indicates whether deep copy is performed. True indicates deep copy and false indicates shallow copy

Target Object Type Target Object to which member attributes of other objects will be attached;

Object1 objectN (Optional), the first and NTH objects of type Object to be merged.

var array1 = [1.2.3.4];
var newArray = $.extend(true,[],array1); // True indicates the deep copy, false indicates the shallow copy
Copy the code

3.4 Lodash function library to achieve deep copy

Lodash Chinese website

let result = _.cloneDeep(test)
Copy the code

3.5 Reflect method

Reflect profile

function isObject(val) {
  returnval ! =null && typeof val === 'object' && Array.isArray(val) === false;
}
function deepClone(obj) {
  let isArray = Array.isArray(obj)
  letcloneObj = isArray ? [...obj] : { ... obj }Reflect.ownKeys(cloneObj).forEach(key= > {
    cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
  })
  return cloneObj
}

let a = [1.2.3.4]
let b = deepClone(a);
a[0] =2;
console.log(a,b); / / (2, 2, 3, 4] [1, 2, 3, 4]
let obj1 = {
  a: 1.b: 2.c: {
    c1: 3.c2:function(){
      console.log('Deep copy')}}}let obj2 = deepClone(obj1)
obj2.c.c1 = 4
console.log(obj1,obj2); // {a:1,b:2,c:{c1:3,c2:f}} {a:1,b:2,c:{c1:4,c2:f}}
Copy the code

3.6 Manually Implementing deep Copy

let obj1 = {
   a: 1.b: 2
}
let obj2 = {
   a: obj1.a,
   b: obj1.b
}
obj2.a = 3;
alert(obj1.a); / / 1
alert(obj2.a); / / 3
Copy the code

3.7 the Object. The assign method

Note:

If the value of an Object is a basic type, you can use object. assign to implement deep copy

// The value of the object is the basic type
var obj = {
  a: 1.b: 2,}var obj1 = Object.assign({}, obj); // obj assigns a null {}
obj1.a = 3;
console.log(obj.a) / / 1
Copy the code

3.8 Slice implements deep copies of arrays

Note:

When the values in the array are basic data types, such as String, Number, or Boolean, it is a deep copy.

When the value in the Array is a reference data type, such as Object or Array, it is a shallow copy.

// When the values in the array are basic data types, such as String, Number, Boolean, it is a deep copy
// When the values in the Array refer to the data type, such as Object or Array, it is a shallow copy
var arr1 = ["1"."2"."3"]; 
var arr2 = arr1.slice(0);
arr2[1] = "9";
console.log(arr1);  / / / "1", "2", "3"]
console.log(arr2);  / / / "1", "9", "3"]
Copy the code

3.9 Concat Implements deep copies of arrays

Note:

When the values in the array are basic data types, such as String, Number, or Boolean, it is a deep copy.

When the value in the Array is a reference data type, such as Object or Array, it is a shallow copy.

// If the value in the array is a basic data type, such as String, Number, Boolean, it is a deep copy;
// When the value in the Array is a reference data type, such as Object, Array, it is a shallow copy;
var arr1 = ["1"."2"."3"];
var arr2 = arr1.concat();
arr2[1] = "9";
console.log(arr1); / / / "1", "2", "3"]
console.log(arr2); / / / "1", "9", "3"]

var arr1 = [{a:1}, {b:2}, {c:3}];
var arr2 = arr1.concat();
arr2[0].a = "9";
console.log(arr1[0].a); / / 9
console.log(arr2[0].a); / / 9
Copy the code

3.10 Using var newObj = object.create (oldObj)

Note: Deep copies of methods in objects cannot be implemented;

function deepClone(initalObj, finalObj) {    
  var obj = finalObj || {};    
  for (var i in initalObj) {        
    var prop = initalObj[i];  // Avoid an infinite loop caused by cross-referencing objects, such as initalobj. a = initalObj
    if(prop === obj) {            
      continue;
    }        
    if (typeof prop === 'object') {
      obj[i] = (prop.constructor === Array)? [] :Object.create(prop);
    } else{ obj[i] = prop; }}return obj;
}

let obj1 = {
  a: 1.b: 2.c: {
    c1: 3.c2:function(){
      console.log('Deep copy')}}}let obj2 = deepClone(obj1)
obj2.c.c1 = 4
console.log(obj1,obj2); // {a:1,b:2,c:{c1:3,c2:f}} {a:1,b:2,c:{c1:4}}
Copy the code

3.11 Implementing Deep Copy using Extended Operators

Note:

When value is a basic data type, such as String, Number, or Boolean, it is a deep copy.

If value is a reference type, such as Object or Array, it is a shallow copy.

let obj1 = {
  a: 1.b: 2.c: {
    c1: 3.c2:function(){
      console.log('Deep copy')}}}letobj2 = {... obj1}{c1:3}} {c1:3}
obj2.c.c1 = 4        // Change the value inside the object
console.log(obj1,obj2);  // {a:1,b:2,c:{c1:4,c2:f}} {a:1,b:2,c:{c1:4,c2:f}}

letobj3 = {... obj1} obj3.c = {c1:5}     // Changing the referenced object actually changes the address of the referenced object
console.log(obj1,obj3);   // {a:1,b:2,c:{c1:4,c2:f}} {a:1,b:2,c:{c1:5}}
Copy the code