Глубокий и поверхностный анализ JavaScript и реализация рукописного глубокого копирования

1. Когда дело доходит до глубокой и поверхностной копии JavaScript, она должна начинаться с ее «источника» — двух основных типов данных JavaScript (базовый тип данных и ссылочный тип данных).

  1. Особенности базовых типов данных: данные хранятся непосредственно в стеке.
  2. Характеристики ссылочного типа данных: ссылка на объект хранится в стеке, а реальные данные хранятся в куче памяти.
  • Основные типы данных: String, Number, Boolean, Null, Undefined, Symbol, BigInt.
  • Тип ссылочных данных: Объект.

2. Разница между глубоким и поверхностным копированием.

  • Неглубокое копирование: копируйте только указатель на объект, а не сам объект, а старый и новый объекты по-прежнему используют одну и ту же память.
  • Глубокая копия: будет создан идентичный объект.Новый объект и исходный объект не используют общую память, и изменение нового объекта не изменит исходный объект.

(Примечание. В узком смысле глубокое и поверхностное копирование предназначено только для ссылочных типов данных, а базовые типы данных — это только операции присваивания)

 

3. Оригинальный метод в JavaScript реализует ограниченную «глубокую и поверхностную копию».

  • Object.assign({}, obj): когда obj является однослойным объектом, Object.assign() в это время может реализовать «глубокое копирование», а когда obj является многослойным объектом, то Object.assign({ }, obj) может реализовать только «поверхностное копирование».
  • JSON.parse(JSON.stringify(xxx)): эта комбинация может реализовать глубокую копию общих объектов (кроме функции, Symbol(), undefined); при реализации функции Symbol(), undefined, это приведет к потере данных, поэтому его нельзя назвать идеальной глубокой копией.

     

4. Затем, если вы хотите реализовать полнофункциональную и высокосовместимую глубокую копию на JS, то вам придется написать функцию глубокой копии самостоятельно (PS: Это также обязательный вопрос на собеседовании, и вам будет предложено описать основная идея реализации если не писать от руки).

Основная идея реализации: с помощью рекурсивного мышления проходить объекты и массивы до тех пор, пока они не станут всеми базовыми типами данных, а затем копировать их, то есть глубокое копирование.

// 深拷贝:对对象内部进行深拷贝,支持 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;
    }

 

Supongo que te gusta

Origin blog.csdn.net/Yi2008yi/article/details/122479001
Recomendado
Clasificación