Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities.

Shallow copy

Creates a new object to accept the object value to be copied or referenced again. If the object property is a primitive data type, the value of the primitive type is copied to the new object. But if the property is a reference data type, the copy is an address in memory, and if one object changes the address in memory, the other object will be affected.

Object.assign

The object.assign () method is used to assign the values of all enumerable properties from one or more source objects to target objects. It will return the target object.

Object.assign(target, ... sources)

const target = { a: 1.b: 2 }
const source = { b: 4.c: 5 }
const returnedTarget = Object.assign(target, source)

console.log(target)           // Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget)   // Object { a: 1, b: 4, c: 5 }
Copy the code

Note the following when using object. assign:

  • It does not copy the object’s inherited properties;
  • It does not copy the object’s non-enumerable properties;
  • You can copySymbolType property.

Object.assignIterate over the properties of the original object, assigning them to the corresponding properties of the target object by copying

Extended operator

You can use the extension operator to make a shallow copy while constructing an object.

let cloneObj = { ... obj };

/* A copy of the object */
let obj = {a:1.b: {c:1}}
letobj2 = {... obj} obj.a =2
console.log(obj)    //{a:2,b:{c:1}} 
console.log(obj2)   //{a:1,b:{c:1}}
obj.b.c = 2
console.log(obj)    //{a:2,b:{c:2}} 
console.log(obj2)   //{a:1,b:{c:2}}

/* Copy the array */
let arr = [1.2.3]
let newArr = [...arr]  / / newArr [1, 2, 3]
Copy the code

Concat copies arrays

var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])

let arr = [1.2.3]
let newArr = arr.concat()
newArr[1] = 100
console.log(arr)      // [1, 2, 3]
console.log(newArr)   // [1, 100, 3]
Copy the code

Slice copy array

arr.slice([begin[, end]])

let arr = [1.2, {val: 4}]
let newArr = arr.slice()
newArr[2].val = 1000
console.log(arr)     // [ 1, 2, { val: 1000 } ]
Copy the code

Deep copy

A shallow copy simply creates a new object and copies the values of the original object’s primitive type, while a reference data type copies only one layer of properties. Deep copy is different. For complex reference data types, a full memory address is created in the heap and the original object is copied over. The two objects are independent and unaffected.

A complete copy of an object from memory to the target object, and a new space in the heap memory to store the new object, and the modification of the new object does not change the original object, the two achieve true separation.

JSON.stringify()

Json.stringify () serializes an object into a JSON string, converts the contents of the object into a string, and finally generates a new object from the JSON string using json.parse ().

let obj1 = { a:1.b: [1.2.3]}let str = JSON.stringify(obj1)
let obj2 = JSON.parse(str)
console.log(obj2)   / / {a: 1, b: [1, 2, 3]}
obj1.a = 2
obj1.b.push(4)
console.log(obj1)   / / {2, a: b: [1, 2, 3, 4]}
console.log(obj2)   / / {a: 1, b: [1, 2, 3]}
Copy the code

Using json.stringify () requires caution

  1. If the value of the copied object has a function,undefined,symbolThese types, afterJSON.stringifyThe key/value pair disappears in the serialized string;
  2. copyDateThe reference type becomes a string;
  3. Unable to copy non-enumerable properties;
  4. Unable to copy object’s prototype chain
  5. copyRegExpReference types become empty objects;
  6. Object containingNaN,InfinityAs well as-Infinity.JSONThe result of serialization will becomenull;
  7. Looping applications that cannot copy objects, i.e. objects are looped (obj[key] = obj).

The recursive implementation

// Check whether the type is complex
const isComplexDataType = obj= > (typeof obj === 'object' || typeof obj === 'function') && (obj ! = =null)

const deepClone = function (obj, hash = new WeakMap(a)) {
  // The date object returns a new date object
  if (obj.constructor === Date)
    return new Date(obj)       

  The regular object returns a new regular object directly
  if (obj.constructor === RegExp)
    return new RegExp(obj)     

  // If the loop is referenced, use weakMap
  if (hash.has(obj)) return hash.get(obj)
  
  / / the use of Object getOwnPropertyDescriptors method can obtain all attributes of the Object, and the corresponding characteristics
  let allDesc = Object.getOwnPropertyDescriptors(obj)

  // Walks through the properties of all keys of the passed argument
  let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)

  // Inherit the prototype chain
  hash.set(obj, cloneObj)

  for (let key of Reflect.ownKeys(obj)) {
    cloneObj[key] = (isComplexDataType(obj[key]) && typeofobj[key] ! = ='function')? deepClone(obj[key], hash) : obj[key] }return cloneObj
}

// Here is the validation code
let obj = {
  num: 0.str: ' '.boolean: true.unf: undefined.nul: null.obj: { name: 'I am an object'.id: 1 },
  arr: [0.1.2].func: function () { console.log(I'm a function.)},date: new Date(0),
  reg: new RegExp('/ I'm a regular /ig'),Symbol('1')]: 1,}Object.defineProperty(obj, 'innumerable', {
  enumerable: false.value: 'Non-enumerable properties'
})

obj = Object.create(obj, Object.getOwnPropertyDescriptors(obj))
obj.loop = obj    // Set loop to a property referenced in a loop
let cloneObj = deepClone(obj)
cloneObj.arr.push(4)
console.log('obj', obj)
console.log('cloneObj', cloneObj)
Copy the code

One last word

If this article is helpful to you, or inspired, help pay attention to it, your support is the biggest motivation I insist on writing, thank you for your support.