1. Understand the data types of JS

Js data types are divided into basic data types and reference data types

Basic data types

Number, string, Boolean, undefined, null, symbol variable values stored in the stack memory, can be directly changes the value of the variable depth copy Ex. :

The first line of code allocates a memory address for the identifier A, which stores the value 100

Line 2: Copy the contents of A to the identifier aCopy, which points to the same memory address as A

Line 3: Assign a new value to aCopy, which creates a new memory address and stores the value 10000

If you change the value of aCopy, it does not change the value of a. This is because a is a primitive data type, and the primitive data type cannot be modified. In other words, you need to create a new memory address to store the new value

Reference data types:

Object,RegExp,math,Date examples:

The first line of code: assign a memory address to the identifier B and store it on the stack. The value of this memory address will be assigned another address, and this other address will refer to the data structure such as the heap, and the corresponding attribute will be created

Line 2: Copy the contents of B to the identifier bCopy, bCopy and B now point to the same memory address. The link between bCopy and B is the same between stack and heap. If bCopy wants to change its value, it needs to find the value of the property in the heap and modify it. Note: this is a shallow copy

Third line of code: change name:’Ali’ to ‘Tom’, so the value of b also changes

Summary: Basic data types and reference types are stored in different ways. There is no depth copy for basic data types, but only for reference types

2. Deep and shallow copies

Deep copy: does not affect the value of the original object, but creates a new memory address shallow copy: affects the value of the original object, but adds a pointer to the variable stack memory

Shallow copy method

1.Object.assign()

The object.assign () method copies the enumerable properties of any number of source objects to the target Object and returns the target Object.

let objA = { Ali: {age: 10},color:'blue' };
let objB = Object.assign({}, objA);
objB.Ali.age = 50;
objB.color = 'red'
console.log(objA,objB); 
Copy the code

As you can see, object.assign () cannot implement deep copy for objects whose attribute values are complex types of objects

2. The _. Clone method of lodash

The library also provides _. Clone for Shallow Copy, which we’ll cover later.

var _ = require('lodash'); var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3] }; var obj2 = _.clone(obj1); console.log(obj1.b.f === obj2.b.f); // true console.log(obj1.c === obj2.c); //falseCopy the code

3. Expand operator…

The expansion operator is an ES6 / ES2015 feature that provides a very convenient way to perform shallow copies, the same functionality as object.assign ().

let obj1 = { name: 'Kobe', address:{x:100,y:100}}
let obj2= {... obj1}
obj1.address.x = 200;
obj1.name = 'wade'
console.log(obj1,obj2)
Copy the code

4.Array.prototype.concat()

let arr = [1, 3, {
    username: 'kobe'
    }];
let arr2 = arr.concat();    
arr2[2].username = 'wade';
console.log(arr);
Copy the code

5.Array.prototype.slice()

let arr = [1, 3, {
    username: ' kobe'
    }];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr); // [ 1, 3, { username: 'wade' } ]
Copy the code

Deep copy implementation

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) copies the codeCopy the code

Json.stringify converts an object into a JSON string, and json.parse parses the string into an object. As it goes, new objects are created, and the object opens up a new stack for deep copy.

This method can do deep copies of arrays or objects, but it can’t handle functions and regees, because when these are processed based on json.stringify and json.parse, the resulting re is no longer a re (becomes an empty object) and the resulting function is no longer a function (becomes null).

Take the following example:

let arr = [1, 3, { username: ' kobe' },function(){}]; let arr4 = JSON.parse(JSON.stringify(arr)); arr4[2].username = 'duncan'; Console. log(arr, arr4) copies the codeCopy the code

2. The _. CloneDeep method of the lodash library

The library also provides _. CloneDeep for 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 copies the codeCopy the code

3. The jQuery. The extend () method

Jquery provides a $.extend for Deep Copy

$.extend(deepCopy, target, object1, [objectN])// Extend (deepCopy, target, object1, [objectN]Copy the code
var $ = require('jquery'); var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3] }; var obj2 = $.extend(true, {}, obj1); console.log(obj1.b.f === obj2.b.f); // false copies the codeCopy the code

4. Handwritten recursive method

The recursive method implements the principle of deep cloning: iterating through objects and arrays until they contain all the basic data types, and then copying, which is called deep copy.

There is a special case needs to pay attention to is the condition of the circular reference object, the object’s properties directly refer to its own situation, 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, Return if there is, continue to copy if there is not, so as to cleverly solve the problem of circular reference. If in doubt about this, please read carefully how ConardLi can write a deep copy to impress the interviewer. This article.

function deepClone(obj, hash = new WeakMap()) { if (obj === null) return obj; If (obj instanceof Date) return new Date(obj); if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); If (typeof obj! == "object") return obj; If (hash. Get (obj)) return hash. Get (obj); let cloneObj = new obj.constructor(); Set (obj, cloneObj); // Constructor points to the current class's own hash.set(obj, cloneObj); For (let key in obj) {if (obj.hasOwnProperty(key)) {cloneObj[key] = deepClone(obj[key], hash); } } return cloneObj; } let obj = { name: 1, address: { x: 100 } }; obj.o = obj; // let d = deepClone(obj); obj.address.x = 200; console.log(d);Copy the code

Reference link: juejin.cn/post/684490…