[Js shallow copy and deep copy]

Js shallow copy and deep copy

Js shallow copy and deep copy are only for reference data types like Object or Array. Students who want to know some data types of Js can refer to my other article js data type and type judgment for details . I won’t elaborate here. .

shallow copy:

For example, when we perform simple assignment processing on some data types, and then use new variables to change the values ​​of the attributes inside, we will find that the original data has also been changed, as shown in the following example:

let obj = {
    
    
 a: '12',
 b: 2
}
let simpleCopy = obj
simpleCopy.b = 5 // 或者执行 obj.b = 5 ,输出结果一致
console.log(obj) // {a: '12', b: 5}
console.log(simpleCopy) // {a: '12', b: 5}

This is because values ​​of reference data types are accessed by reference. Both obj.b and simpleCopy.b point to the address of the stored value, not the value itself.

Deep copy:

When we process data, sometimes we definitely don't want our original data to be replaced or changed. Deep copy is to solve this problem. Below I will list some common deep copy methods.

Method 1: Object.assign

The Object.assign() method is used to copy the values ​​of all enumerable properties from one or more source objects source to a target object. It will return the target object target. But what we need to pay attention to is that it only makes a deep copy of the outermost layer, that is, when there are objects nested in the object, the nested object is still shallow copied.

let obj = {
    
    
  a: '12',
  b: 2,
  c: {
    
     K1: NaN, K2: function(){
    
    } }
}
let deepCopy = Object.assign({
    
    }, obj)
deepCopy.b = 5
deepCopy.c.K1 = Infinity
console.log(obj)
console.log(deepCopy)

Output result:

insert image description here

Method 2: JSON.parse and JSON.stringify

This is a common deep copy implementation, and I used this method for some data processing before.

let obj = {
    
    
  a: '12',
  b: 2,
  c: {
    
     K1: NaN, K2: function(){
    
    } }
}
let deepCopy = JSON.parse(JSON.stringify(obj))
deepCopy.b = 5
deepCopy.c.K1 = Infinity
console.log(obj)
console.log(deepCopy)

Output result:

insert image description here

Disadvantages: Here we can see that there seems to be no problem, and a copy of the data is successfully copied without affecting the original data. However, in the JSON.stringify method, some data generated by the constructor will lose the constructor of the object during data conversion. Like the following situation:

let obj = {
    
    
 a: '12',
 b: 2,
 c: new Date(),
 d: NaN
}
let deepCopy = JSON.parse(JSON.stringify(obj))
deepCopy.b = 5
console.log(obj)
console.log(deepCopy)

Output result:

insert image description here

Data such as Date, Error, RegExp, function, NaN, Infinity, -Infinity, and undefined will lose or be replaced by the JSON.stringify method. In this case, it is not feasible to use this method in some situations.

Method 3: deepCopy recursive assignment (recommended)

Compared with the above several deep copy methods, there are more or less disadvantages, so we can encapsulate a deep copy method by ourselves.

function cloneDepth(initalObj, finalObj = {
     
     }) {
    
    
  let bol = isArrayOrObject(initalObj)
  if (!bol) return initalObj 
  Object.keys(initalObj).forEach((key) => {
    
    
    bol = isArrayOrObject(initalObj[key])
    finalObj[key] = bol ? cloneDepth(initalObj[key], bol === 'Array' ? [] : {
    
    }) : initalObj[key]
  })
  // // 或者采用 for in
  // for (var key in initalObj) {
    
    
  //   bol = isArrayOrObject(initalObj[key])
  //   finalObj[key] = bol ? cloneDepth(initalObj[key], bol === 'Array' ? [] : {}) : initalObj[key]
  // }
  return finalObj
}
function isArrayOrObject(list) {
    
    
  let isBool = false
  switch (outputDataType(list)) {
    
    
    case 'Object': isBool = 'Object'; break;
    case 'Array': isBool = 'Array'; break;
    default: isBool = false; break;
  }
  return isBool
}
function outputDataType(data) {
    
    
  let dataTypeStr = Object.prototype.toString.call(data)
  dataTypeStr = dataTypeStr.match(/\[object (\S*)\]/)[1]
  return dataTypeStr
}

Call our encapsulated method

let obj = {
    
    
  a: '12',
  b: 2,
  c: {
    
     k1: '1', k2: 23, k3: true },
  d: ['11', 2, null, undefined, new Date()],
  e: function () {
    
     },
  f: null,
  h: new Date(),
  i: Infinity,
  j: new RegExp('12'),
  n: NaN
}
let deepCopy = cloneDepth(obj)
console.log(obj)
console.log(deepCopy)

Output result:

insert image description here

It is exactly the same as the original data, so the encapsulated cloneDepth method can be used well.

Guess you like

Origin blog.csdn.net/weixin_42927679/article/details/125782617