preface

JS data types are mainly divided into two types: basic data type and reference data type.

The basic type of data is stored directly in stack memory; Data of reference type is stored in heap memory, and the memory address (pointer) of this data is stored in stack memory.

let a = 'first'; let arr1 = [1, 2, '3']; let obj = { a: 'second', b: 16, c: a, d: arr1}; a = 'first1'; console.log(obj) // { a: 'second', b: 16, c: 'first', d: [1, 2, "3"]} arr1.push('44'); Console. log(obj) console.log(obj) {a: 'second', b: 16, c: 'first', d: [1, 2, "3", "44"]} // change obj.dobj.d.ush (55) // change arr1 console.log(arr1); // [1, 2, "3", "44", 55]Copy the code

When you change the value of a reference type, any variable that references that value also changes.

Looking at the example above, you can see that if our variable points to the same memory address, changing its value will affect all variables that refer to it. To solve the above problem, we need to make shallow or deep clone copies of the values.

What is theShallow copyandDeep copy

Shallow and deep copies are mainly for objects (including functions, Regex, and Date) and arrays.

Shallow copy only copies the memory address (pointer) that points to an object, not the object itself. The old and new objects share one memory address, and modification of either one affects the other. A shallow copy creates a new object and copies the properties of the original object one by one. If the property of the original object is the base type, the copy is the value of the property; If the property of the original object is a reference type, the copy is the memory address, so the modification will affect each other.

Deep copy creates an additional identical object, the old and new objects do not share the same memory address, and changes do not affect each other.

Shallow copy implementation

Shallow copy implements only one layer of copy, not deep copy

Object shallow copy

1. Expand operators

let obj = { a: '', b: null, c: undefined, d: ['1', 2, 3, { a: 12 }], }; let shallowCloneObj = {... obj}; console.log(shallowCloneObj)Copy the code

2. Object.assign()

let obj = {
  a: '',
  b: null,
  c: undefined,
  d: ['1', 2, 3, { a: 12 }],
};
let shallowCloneObj = Object.assign(obj);
console.log(shallowCloneObj)
Copy the code

3. for.. The in traverse

function shallowClone(obj) { if (! isObject(obj)) return obj; const cloneObj = Array.isArray(obj) ? [] : {}; for (let prop in obj) { if (obj.hasOwnProperty(prop)) { cloneObj[prop] = obj[prop]; } } return cloneObj; };Copy the code

4. Assign values in sequence

let obj = {
  a: '',
  d: ['1', 2, 3, { a: 12 }],
};
let shallowCloneObj = {};
shallowCloneObj.a = obj.a
shallowCloneObj.d = obj.d
Copy the code

Array shallow copy

Array.prototype methods that return a new Array can be considered shallow copies

1. Array.prototype.slice()

let arr = [1, 2, 3, 4];

console.log(arr.slice(0))

Copy the code

2. Array.prototype.concat()

let arr = [1, 2, 3, 4];
console.log(arr.concat([]))
Copy the code

3. Array.prototype.map()

let arr = [1, 2, 3, 4];
console.log(arr.map((ele) => ele))
Copy the code

3. Array.prototype.filter()

let arr = [1, 2, 3, 4];
console.log(arr.filter(() => true))
Copy the code

4. Expand operators

let arr = [1, 2, 3, 4];
console.log([...arr])
Copy the code

5. Assign values in sequence

Can be used when the value is simple

let arr = [1, 2];
let shallowCloneArr = [arr[0], arr[1]]
Copy the code

Handwriting to achieve shallow copy

Const isObject = (obj) => typeof obj === 'object' &&obj! == null; const shallowClone = (obj) => { if (! isObject(obj)) return obj; const cloneObj = Array.isArray(obj) ? [] : {}; for (let prop in obj) { if (obj.hasOwnProperty(prop)) { cloneObj[prop] = obj[prop]; } } return cloneObj; }Copy the code

Deep copy implementation

JSON.stringfy()

Json.stringfy () is a common deep-copy method on the front end. It serializes an object into a JSON string, converts the contents of the object into a string, and then uses json.parse () to generate a new object from the JSON string.

let obj = { a: '', b: null, c: undefined, // undefined d: ['1', 2, 3, { a: 12 }], e: {m: 5, n: '66'}, m: New Date(), // Date n: NaN, f: function fn(){console.log('11')}, // function r: new RegExp(' d'), // RegExp s: Symbol(66), // Symbol [Symbol('test')]: 1,} // Define the unenumerable attribute object.defineProperty (obj, 'innumerable', {enumerable: false, value: 'innumerable'}); console.log(JSON.parse(JSON.stringify(obj))); / * * the results are as follows: a "b" : null d: (4) [" 1 ", 2, 3, {...}] e: {5, m: n: "66"} m: "the 2021-09-09 T11:42:05. 771 z, n: null r: {} * * /Copy the code

But there’s a catch:

  1. The value of the copied object, if anyfunction,undefined,SymbolThese types, afterJSON.stringifyThe key/value pair disappears in the serialized string
  2. If it isRegExpObject, will become{}
  3. If it isDateWill be converted to a string
  4. NaNWill be converted tonull
  5. Non-enumerable properties (enumerable: false), cannot be copied

lodash.cloneDeep()

Source:

lodash.cloneDeep()

Handwritten recursive implementation

Function cloneDeep(target) {// If (! typeof targe === 'object') { return target; } // define an empty object let newObj = array.isarray (target)? [] : {}; for(let key in target) { newObj[key] = typeof target[key] === 'object' ? cloneDeep(target[key]) : target[key] } return newObj; }Copy the code

thinking

The difference between assignment and shallow copy

  1. If it’s a basic type, you can say that assignment is the same as shallow copy,
  2. In the case of reference type data, assignment assigns the address of the object in the stack, not the data in the heap. The two data affect each other. If one changes, the other changes. A shallow copy creates a new object and copies the properties of the original object one by one. If the property of the original object is the base type, the copy is the value of the property; If the attribute of the original object is a reference type

conclusion

If this article helped you, please like 👍 and follow ⭐️.

If there are any errors in this article, please correct them in the comments section 🙏🙏.