оригинал:Вы действительно клонируете объекты в эпоху 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, Ифэн Руан.Все хорошо представлено.
Ладно, так и быть, младшие школьники в мире фронтенда, пожалуйста, поправьте меня за мои недостатки.