предисловие
Когда я раньше ходил в компанию на собеседование, интервьюер задал мне вопрос и сказал: «Как я могу глубоко скопировать объект». В то время я немного обрадовался: стоит ли еще думать над таким простым вопросом? Поэтому он выпалил: «Есть два широко используемых метода: первый — это JSON.parse(JSON.stringify(obj)), а второй можно сделать с помощью for…in плюс рекурсия». Интервьюер кивнул и был вполне удовлетворен. В то время я не слишком заботился об этой проблеме, пока не вспомнил об этой проблеме некоторое время назад и не обнаружил, что два метода, упомянутых выше, имеют ошибки.
Задайте вопрос
Так что же это за ошибка, упомянутая выше?
- копия специального объекта
Сначала давайте представим объект со следующими членами, независимо от обычных типов:
const obj = {
arr: [111, 222],
obj: {key: '对象'},
a: () => {console.log('函数')},
date: new Date(),
reg: /正则/ig
}
Затем мы используем два вышеуказанных метода для копирования один раз
JSON-метод
JSON.parse(JSON.stringify(obj))
Выходной результат:
Отсюда видно,obj
Обычные объекты и массивы могут быть скопированы, однакоdate
Объект становится строкой, функция сразу исчезает, а регулярка становится пустым объектом.
посмотри сноваfor...in
добавить рекурсивный метод
рекурсия
function isObj(obj) {
return (typeof obj === 'object' || typeof obj === 'function') && obj !== null
}
function deepCopy(obj) {
let tempObj = Array.isArray(obj) ? [] : {}
for(let key in obj) {
tempObj[key] = isObj(obj[key]) ? deepCopy(obj[key]) : obj[key]
}
return tempObj
}
результат:
в заключении
В приведенном выше тесте видно, что ни один из этих двух методов не может скопировать функцию,date
,reg
объект типа;
- звенеть
Что такое кольцо?
Кольцо — это циклическая ссылка на объект, в результате чего само становится замкнутым циклом, например следующий объект:
var a = {}
a.a = a
Использование двух вышеуказанных методов для его копирования приведет к прямому сообщению об ошибке.
решение
- звенеть
может использоватьWeakMap
В структуре хранятся объекты, которые были скопированы, и каждый раз, когда делается копия,WeakMap
Запрос, был ли скопирован объект, если он был скопирован, выньте объект и верните, будетdeepCopy
Функция преобразуется следующим образом
function deepCopy(obj, hash = new WeakMap()) {
if(hash.has(obj)) return hash.get(obj)
let cloneObj = Array.isArray(obj) ? [] : {}
hash.set(obj, cloneObj)
for (let key in obj) {
cloneObj[key] = isObj(obj[key]) ? deepCopy(obj[key], hash) : obj[key];
}
return cloneObj
}
Копировать результат кольца:
- копия специального объекта
Решение этой проблемы более хлопотное, потому что слишком много типов объектов, требующих специального обращения, поэтому я обращаюсь к MDNструктурированная копия, а затем объедините решения, чтобы решить кольцо:
// 只解决date,reg类型,其他的可以自己添加
function deepCopy(obj, hash = new WeakMap()) {
let cloneObj
let Constructor = obj.constructor
switch(Constructor){
case RegExp:
cloneObj = new Constructor(obj)
break
case Date:
cloneObj = new Constructor(obj.getTime())
break
default:
if(hash.has(obj)) return hash.get(obj)
cloneObj = new Constructor()
hash.set(obj, cloneObj)
}
for (let key in obj) {
cloneObj[key] = isObj(obj[key]) ? deepCopy(obj[key], hash) : obj[key];
}
return cloneObj
}
Скопируйте результат:
Полную версию можно посмотретьглубокая копия lodash
- копия функции
Но структурированная копия на MDN по-прежнему не имеет копии функции решения
Пока я думал только об использованииeval
Метод копирует функцию, но этот метод может действовать только на стрелочные функции, если онfun(){}
Ошибка в этой форме
Скопируйте функцию, чтобы добавить тип функции
скопировать результат
тип ошибки
постскриптум
Глубокая копия JavaScript — это не только упомянутые выше ямки, но и проблема, как скопировать свойства в цепочке прототипов? Как скопировать неперечислимые свойства Как скопироватьError
Ямки предметов и т.п. здесь повторяться не будут.
Однако в повседневном процессе все же рекомендуется использовать метод JSON.Этот метод покрыл большую часть потребностей бизнеса, поэтому нет необходимости усложнять простые вещи.Однако, если интервьюер сталкивается с резким ответом на этот вопрос во время интервью, это определенно будет шоу У него есть лицо.