One , data type

      Data is divided into basic data types (String, Number, Boolean, Null, Undefined,Symbol(new in ES 6) and
Reference data type ( Collectively referred to as  Object type , In terms of segmentation, there are :Object ,Array ,Date ,RegExp,Function… ).

*
Characteristics of basic data types : Store directly on the stack (stack) Data in

* Characteristics of reference data types : The object is stored in the stack reference , The real data is stored in heap memory
      The reference data type stores a pointer in the stack , The pointer points to the starting address of the entity in the heap . When the interpreter looks for a reference value , Its address in the stack is retrieved first , Get the address and get the entity from the heap .

Two , Shallow copy and deep copy

Deep copy and shallow copy are only for Object and Array Such a reference data type .

The schematic diagram of shallow copy and deep copy is as follows :

Shallow copy copies only the pointer to an object, not the object itself , The old and new objects still share the same memory .

But deep copy creates as like as two peas. , The new object does not share memory with the original object , Modifying a new object does not change to the original object .

Three , The difference between assignment and shallow copy

* When we assign an object to a new variable , The assignment is actually the address of the object in the stack , Instead of data in the heap
. That is, two objects point to the same storage space , No matter which object changes , It's all about changing the contents of the storage space , therefore , The two objects are linked .
* A shallow copy is a bitwise copy of an object , It creates a new object
, This object has an exact copy of the property values of the original object . If the property is a base type , What you copy is the value of the base type ; If the property is a memory address ( reference type ), The copy is the memory address
, So if one of the objects changes the address , It affects another object . Namely : The default copy constructor only makes shallow copy copies of objects ( Copy one member at a time ), That is, only the object space is copied, not the resources .
Let's start with two examples , What changes will be made to the original object by comparing assignment with shallow copy ?

  Object Assignment :

 var obj1 = {

    'name' : 'zhangsan',

    'age' :  '18',

    'language' : [1,[2,3],[4,5]],

};

var obj2 = obj1;

obj2.name = "lisi";

obj2.language[1] = [" Two "," Three "];

console.log('obj1',obj1)

console.log('obj2',obj2)

 

Light copy :

 var obj1 = {

    'name' : 'zhangsan',

    'age' :  '18',

    'language' : [1,[2,3],[4,5]],  //Array

};

 var obj3 = shallowCopy(obj1);

 obj3.name = "lisi";

 obj3.language[1] = [" Two "," Three "];

 function shallowCopy(src) {

    var dst = {};

    for (var prop in src) {

        if (src.hasOwnProperty(prop)) {

            dst[prop] = src[prop];

        }

    }

    return dst;

}

console.log('obj1',obj1)

console.log('obj3',obj3)

In the example above ,obj1 It's raw data ,obj2 It is obtained by the assignment operation , and obj3 Shallow copy . We can clearly see the impact on the raw data , Please see the table below for details :

Four , Implementation of shallow copy

1.Object.assign()

Object.assign() Method can copy the enumerable properties of any number of source objects to the target objects , It then returns the target object . however
Object.assign() It's a shallow copy , What is copied is a reference to an object's properties , Not the object itself .

var obj = { a: {a: "kobe", b: 39} };

var initalObj = Object.assign({}, obj);

initalObj.a.a = "wade";

console.log(obj.a.a); //wade

 

be careful : When object When there's only one floor , It's a deep copy

let obj = {

    username: 'kobe'

    };

let obj2 = Object.assign({},obj);

obj2.username = 'wade';

console.log(obj);//{username: "kobe"}

 

2.Array.prototype.concat()

let arr = [1, 3, {

    username: 'kobe'

    }];

let arr2=arr.concat();    

arr2[2].username = 'wade';

console.log(arr);

 

Modifying the new object will change to the original object :

 

3.Array.prototype.slice()

let arr = [1, 3, {

    username: ' kobe'

    }];

let arr3 = arr.slice();

arr3[2].username = 'wade'

console.log(arr);

 

Similarly, modifying the new object will change to the original object :

about Array Of slice and concat Supplementary explanation of the method :

Array Of slice and concat Method does not modify the original array , Only a new array with shallow copies of the elements in the original array is returned .

The elements of the original array are copied according to the following rules :

* If the element is an object reference ( Not the actual object ),slice
This object will be copied to the new array . Both object references refer to the same object . If the referenced object changes , The element in the new and original arrays will also change .
* For Strings , Numbers and Boolean values ( no String,Number perhaps Boolean object ),slice
The values are copied to the new array . Modify these strings or numbers or boolean values in other arrays , Another array will not be affected .
Maybe this paragraph is obscure , Let's take an example , Modify the example above :

let arr = [1, 3, {

    username: ' kobe'

    }];

let arr3 = arr.slice();

arr3[1] = 2

console.log(arr,arr3);

 

Five , Implementation of deep copy

1.JSON.parse(JSON.stringify())

let arr = [1, 3, {

    username: ' kobe'

}];

let arr4 = JSON.parse(JSON.stringify(arr));

arr4[2].username = 'duncan';

console.log(arr, arr4)

 

principle :
use JSON.stringify Convert object to JSON character string , Reuse JSON.parse() Parse a string into an object , As soon as we go , New objects are created , And objects will open up new stacks , Realize deep copy .

This method can realize deep copy of arrays or objects , But you can't handle functions

let arr = [1, 3, {

    username: ' kobe'

},function(){}];

let arr4 = JSON.parse(JSON.stringify(arr));

arr4[2].username = 'duncan';

console.log(arr, arr4)

 

that is because JSON.stringify() The method is to add a JavaScript value ( Object or array ) Convert to a JSON character string , Cannot accept function

2. Handwriting recursion method

The principle of deep cloning by recursion : Traversing objects , Arrays up to the inside are primitive data types , And then copy it , It's deep copy

    // Define the function of detecting data type

    function checkedType(target) {

      return Object.prototype.toString.call(target).slice(8, -1)

    }

    // Realize deep cloning --- object / array

    function clone(target) {

      // Determine the data type of the copy

      // initialize variable result Data that becomes the final clone

      let result, targetType = checkedType(target)

      if (targetType === 'object') {

        result = {}

      } else if (targetType === 'Array') {

        result = []

      } else {

        return target

      }

      // Traverse target data

      for (let i in target) {

        // Get each item value of traversal data structure .

        let value = target[i]

        // Whether there is a target value in each object / array

        if (checkedType(value) === 'Object' ||

          checkedType(value) === 'Array') { // object / Objects are nested in the array / array

          // Continue traversing to get value value

          result[i] = clone(value)

        } else { // Get to value Values are basic data types or functions .

          result[i] = value;

        }

      }

      return result

    }

 

3. function library lodash

The library is also available _.cloneDeep used to Deep Copy

 

var _ = require('lodash');

var obj1 = {

    a: 1,

    b: { f: { g: 1 } },

    c: [1, 2, 3]

};

var obj2 = _.cloneDeep(obj1);

console.log(obj1.b.f === obj2.b.f);

// false

 

 

Technology