Deep and shallow copy analysis of JavaScript and implementation of handwritten deep copy

1. When it comes to the deep and shallow copy of JavaScript, it must start from its "source" - the two major data types of JavaScript (basic data type and reference data type).

  1. Features of basic data types: data is stored directly on the stack.
  2. The characteristics of the reference data type: the reference of the object is stored in the stack, and the real data is stored in the heap memory.
  • Basic data types: String, Number, Boolean, Null, Undefined, Symbol, BigInt.
  • Reference data type: Object.

2. The difference between deep and shallow copy.

  • Shallow copy: only copy the pointer to an object, not the object itself, and the old and new objects still share the same memory.
  • Deep copy: An identical object will be created. The new object and the original object do not share memory, and modifying the new object will not change the original object.

(Note: In a narrow sense, deep and shallow copy is only for reference data types, and basic data types are only assignment operations)

 

3. The original method in JavaScript realizes the limited "deep and shallow copy".

  • Object.assign({}, obj): When obj is a single-layer object, Object.assign() at this time can realize "deep copy"; and when obj is a multi-layer object, then Object.assign({}, obj) can only implement "shallow copy".
  • JSON.parse(JSON.stringify(xxx)): This combination can realize the deep copy of common objects (except function, Symbol(), undefined); when implementing function, Symbol(), undefined, It will cause data loss, so it cannot be called a perfect deep copy.

     

4. Then, if you want to implement a full-featured and highly compatible deep copy in JS, then you have to write the deep copy function yourself (PS: This is also a required interview question, and you will be asked to describe the main idea of ​​​​the implementation if you don’t write it by hand) .

The main realization idea: Through recursive thinking, traverse objects and arrays until they are all basic data types, and then copy them, that is, deep copy.

// 深拷贝:对对象内部进行深拷贝,支持 Array、Date、RegExp、DOM
    function deepCopy(params) {
      // 如果不是对象则退出(可停止递归)
      if (typeof params !== 'object') return;
      // 深拷贝初始值:对象/数组
      let newObj = (params instanceof Array) ? [] : {};
      // 使用 for-in 循环对象属性(包括原型链上的属性)
      for (let i in params) {
        // 只访问对象自身属性
        if (params.hasOwnProperty(i)) {
          // 当前属性还未存在于新对象中时
          if (!(i in newObj)) {
            if (params[i] instanceof Date) {
              // 判断日期类型
              newObj[i] = new Date(params[i].getTime());
            } else if (params[i] instanceof RegExp) {
              // 判断正则类型
              newObj[i] = new RegExp(params[i]);
            } else if ((typeof params[i] === 'object') && params[i].nodeType === 1) {
              // 判断 DOM 元素节点
              let domEle = document.getElementsByTagName(params[i].nodeName)[0];
              newObj[i] = domEle.cloneNode(true);
            } else {
              // 当元素属于对象(排除 Date、RegExp、DOM)类型时递归拷贝
              newObj[i] = (typeof params[i] === 'object') ? deepCopy(params[i]) : params[i];
            }
          }
        }
      }
      return newObj;
    }

 

Guess you like

Origin blog.csdn.net/Yi2008yi/article/details/122479001