В эпоху ES6 вы действительно клонируете объекты (2)

JSON ECMAScript 6

оригинал:Вы действительно клонируете объекты в эпоху ES6? (2)

Предыдущий, мы проанализировали, как неглубоко скопировать объект в ES6 с точки зрения дескрипторов символов и перечислимости и атрибутов, опубликованных вНаггетса такжеsegmentfaultВыше, судя по комментариям, некоторым кажется, что они этого не понимают.Сегодня мы используем более простой способ рассказать о проблеме глубокого копирования.

написать впереди

Тема глубокого копирования, кажется, никогда не переставала обсуждаться. В JavaScript нет метода, который мог бы реализовать глубокое копирование. Наш общий метод реализации — это рекурсия иJSON.parse(JSON.stringify())(Я слышал, что нижний уровень все еще использует рекурсию), но общие библиотечные функции могут иметь дело только с общими требованиями (действительно ли существуют необычные требования? Вам действительно нужно использовать глубокое копирование? Вы действительно не признаете, что это проблема с вашим код?). Сегодня я буду изучать, как добиться глубокого копирования с осторожным, серьезным, дотошным (не очень дотошным), ответственным (и не слишком уверенным) отношением.Столько дней напряженной работы и письма, как я могу быть достойным меня кто сдерживал дрожь и печатал на клавиатуре этой холодной зимой...

обычная глубокая копия

Сериализация JSON

JSON.parse(JSON.stringify())Это действительно очень простой и удобный способ его использования.К сожалению, JSON очень принципиальный человек, и он не будет слушать вас. Небезопасные значения JSON автоматически игнорируются при обнаружении, а в массивах возвращается null (чтобы положение ячейки оставалось неизменным).

Небезопасные значения JSON: undefined , function , symbol (ES6+) и объекты, содержащие циклические ссылки (объекты, ссылающиеся друг на друга, образующие бесконечный цикл), не соответствуют стандарту структуры JSON, и языки, поддерживающие JSON, не могут их обрабатывать

рекурсия

ПредыдущийГоворя о неглубоком копировании, мы вначале представили пример поверхностного копирования, а теперь заменим его на простое глубокое копирование.

function deepCopy (obj) {
  if (typeof obj !== 'object') {
    return
  }
  var newObj = obj instanceof Array ? [] : {}
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]
    }
  }
  return newObj
}

Вроде бы не плохо, понятно и можно использовать, общая сцена действительно хороший метод, но сегодня мы рассмотрим необычную сцену.

Сначала выберем неисправности:

  • functionТипа не разобрался (наверное, может быть, он должен быть действительно ненужным, я не собираюсь обсуждать этот товар ниже, если вам интересно, идите и смотритеcall,apply,bind)
  • циклическая ссылка
  • для оценки типаtypeofа такжеinstanceofЭто надежно? (обращать вниманиеtypeof nullяма)
  • множество? []:{},Так просто? несуществующий

циклическая ссылка

Проблема циклических ссылок упоминалась во многих местах выше, давайте сначала посмотрим, что такое циклические ссылки:

var a = {}
a.b = a

Да, это такое античеловеческое существование, но это большая проблема, которую мы не можем игнорировать. Должны ли мы возвращать ноль?undefinedЧто, или отсылка к нему, что ли? Кажется, стандартного ответа нет, эм, тогда следуй своему сердцу!

Типовое суждение

подумайте немного:

typeof null  // "object"
null instanceof Object  // false

Оценка типа неизбежна, но, похоже, у нас нет идеального способа получить нужный нам тип. Давайте рассмотрим несколько распространенных способов:

  • typeof: возвращает строку типа данных выражения, а возвращаемый результат — базовый тип данных js, включаяnumber,boolean,string,object,undefined,function,symbol
  • instanceof: определить, относится ли объект к определенному типу данных или является ли переменная экземпляром объекта; возвращает логический тип. Встроенные типы могут использовать instanceof только через конструктор
  • constructor: это атрибут, принадлежащий каждому объекту экземпляра, и этот атрибут также эквивалентен указателю, который указывает на объект, создавший текущий объект.
  • Object.prototype.toString.call(obj).slice(8,-1): возвращает имя класса

typeofПроблема очевидна:

typeof null  // "object"
typeof function () {}  // "function"
typeof []  // "object"

instanceofРассмотрим мультиглобальный объект (несколькоframeили большеwindowвзаимодействие), в браузере нашему сценарию может потребоваться взаимодействие между несколькими окнами. Несколько окон означают несколько глобальных сред, а разные глобальные среды имеют разные глобальные объекты и, следовательно, разные встроенные конструкторы типов. Это может вызвать некоторые проблемы. Например, выражение[] instanceof window.frames[0].Arrayвернусьfalse,потому чтоArray.prototype !== window.frames[0].Array.prototype

constructorСвойства получают только конструкторы и могут быть изменены вручную,constructor.nameОн просто возвращает имя конструктора, а не имя класса.

Object.prototype.toString.callЭто относительно признанный и надежный метод, однако его также можно искусственно имитировать, это утиный метод, но все же это относительно безопасный метод.

Тип утки: «Если ходит как утка и крякает как утка, то это утка». Языки с динамической типизацией склонны делать то, что вы им позволяете

Типовой анализ

Содержание обсуждения должно быть достаточно подробным.Далее давайте посмотрим, насколько сложны сложные типы данных js.

Наши общие:

Основные типы оболочки (логическое значение, строка, число), функция, массив, дата

Вы обыкновенны, но можете и не думать об этом:

RegExp, Аргументы, Ошибка, NodeList

Вы можете быть не обычным, и вы можете не знать:

Большой двоичный объект, файл, список файлов, данные изображения

ЭС6:

Map, Set, WeakMap, WeakSet, объекты ArrayBuffer, представления TypedArray и представления DataView, Float32Array, Float64Array, Int8Array...

Возможно, список намного меньше, но достаточно, чтобы побеспокоиться о сложности глубоких клонов, реализовывать их по одному не просто, а то и совсем ненужное дело (конечно, можно узнать больше), порекомендуйте несколько отличных решений для справки:

  • клон лодаш, lodash тратит много кода на реализацию большого количества новых стандартных объектов, представленных в ES6. Более того, lodash очень хорошо справляется с объектами с кольцами.
  • клон jQueryОбъекты, отличные от объектов JSON, не могут быть правильно глубоко скопированы
  • Алгоритм структурированного клонирования

напиши в конце

Клоновая часть почти написана, изначально хотел написать содержимое Map и Set, но не нашел нужного места.MDN,Начало работы с ECMAScript 6, Ифэн Руан.Все хорошо представлено.

Ладно, так и быть, младшие школьники в мире фронтенда, пожалуйста, поправьте меня за мои недостатки.