var initialObj = {
object: {
string2: 'Petrov',
object2: {
array2: [{}, {}]
},
object3: {}
},
};
var obj = {};
function deepClone(initialObj) {
for (var key in initialObj.object[key]) {
obj.object[key] = initialObj.object[key];
}
return initialObj;
}
obj = initialObj;
var clonedObj = deepClone(initialObj);
clonedObj.object.object2.array2[1].name = 'Vasya';
console.log(initialObj);
console.log(clonedObj);
Скопирывалитсь 2 объекта, только при изминениии имени, меняется в обоих. Походу скопирывалась ссылка. Как склонирывать? Что бы они были как два независимых объекта. Заранее благодарен за любую помощь.
function cloneObj(obj) {
return JSON.parse(JSON.stringify(obj))
}
У него есть проблемы (например выкинетеся ошибка если в значениях свойст объекта есть функция).
Для решений где все равно какой вложенности объект, имеет значение производительность и значения могут быть любыми бери готовые библиотеки-пакеты: https://www.npmjs.com/package/clone
Если смотреть на задачу как на упражнение, то тебе нужна рекурсивная функция, которая будет делать копии массивов-объектов, вызывя себя для значения массивов-объектов, а примитивные значения возвращать как есть. Ниже набросок решения. isPromitive, isArray, isObject я не реализовывал. В наброске решения куча крайних случаев, но для понимания концепта этого достаточно.
function deepClone(obj) {
if(isPromitive(obj)) {
return obj
} else if (isArray(obj)) {
return obj.map((val) => {
return deepClone(val)
})
} else if (isObject(obj)) {
let res = {}
for (let k in obj) {
res[k] = deepClone(obj[k])
}
return res
}
}
я правильно понимаю что если мы с помощью этой функции склонируем глубокий объект то все ОК, !!НО!! если эту функцию применить к простому объетку то мы не получим клон, а получим ссылку на объект, потому что сработает return obj ?
и если в простом объекте изменить значение свойства оно поменяется везде.
Если я верно понимаю имеется в виду объект без уровней вложенности типа {name: "koko", age: 99}. Для такого объекта isPromitive(obj) должна возвращать false, и выполнится код из другой ветки потому что isObject(obj) будет true. А в той ветке возвращается копия.
Функция isPrimitive должна возвращать true для данных типов число, строка, булевое, null, undefined (вроде все перечислил).
Вот примерный код для проверки предположения. Сразу предупрежу что функции возможно не production-ready потому что не покрыты граничные случаи
function isPrimitive(obj) {
return obj == null ||
typeof obj === 'number' ||
typeof obj === 'string' ||
typeof obj === 'boolean'
}
function isArray(obj) {
return Array.isArray(obj)
}
function isObject(obj) {
return obj != null && typeof obj === 'object'
}
function deepClone(obj) {
if(isPrimitive(obj)) {
return obj
} else if (isArray(obj)) {
return obj.map((val) => {
return deepClone(val)
})
} else if (isObject(obj)) {
let res = {}
for (let k in obj) {
res[k] = deepClone(obj[k])
}
return res
}
}
const obj1 = {
a: 10
}
const obj2 = deepClone(obj1)
obj1.b = 100500
console.log(obj1, obj2)
спасибо я понял, я только учусь, извините если глупо будет , но я так понимаю что если мы клонируем глубокий объект, то из за базового условия для рекурсии последнее значение не будет клоном, оно останется ссылкой на первый объект. т.е. склонируются все значения кроме самого последнего уровня вложенности - на этом уровне все будет ссылками
Глупых вопросов нет. Наличие вопроса означает что задающий его пытается построить ментальную модель происходящего, и проверяет ее корректность через вопросы и практику. Я тоже проходил через кучу моментов непонимания сути происходящего. По субъективному опыту заметил что чем больше забивать на рефлексию (вопросы типа “а почему я это не понимаю”, “а нормально ли это”, “вопрос какой-то глупый” итд), и фокусироваться на формировании картинки происходящего, задачу вопросов и способов проверки корректности ответов, тем глаже идет выяснение предмета.
Есть ли пример кода который бы подтвердил это предположение? Какой объект нужно склонировать чтобы сработал описываемый тобой механизм?
Я попробую написать такой код по тому что понял из твоего комментария, а ты тоже попробуй написать код который подтвердит твое предположение.
Вот код. Я клонирую вложенный объект и добавляю свойства во все оригиналы объектов. Если бы результат бы не был полным клоном, мы бы увидели в копии добавленные свойства. Но их там нет. Рядом вывожу оригинальный объект и там все добавленные свойства видны.
function isPrimitive(obj) {
return obj == null ||
typeof obj === 'number' ||
typeof obj === 'string' ||
typeof obj === 'boolean'
}
function isArray(obj) {
return Array.isArray(obj)
}
function isObject(obj) {
return obj != null && typeof obj === 'object'
}
function deepClone(obj) {
if(isPrimitive(obj)) {
return obj
} else if (isArray(obj)) {
return obj.map((val) => {
return deepClone(val)
})
} else if (isObject(obj)) {
let res = {}
for (let k in obj) {
res[k] = deepClone(obj[k])
}
return res
}
}
const arrObj1 = {a: 1}
const arrObj2 = {a: 2}
const obj1 = {
a: 10,
b: [arrObj1, arrObj2]
}
const obj2 = deepClone(obj1)
obj1.c = 100500
arrObj1.b = 100500
arrObj2.b = 100500
console.log(obj1, obj2)
действительно все работает как нужно! у меня просто в моем коде почему то происходит то что я описал выше (не клонируется последнее значение а остается ссылкой). Теперь у меня есть рабочий пример и буду разбираться где ошибка. Большое вам спасибо !
еще я в isPrimitive добавил тип function потому как если в объекте есть метод он получает undefined при клонировании, а с этим условием все работает замечательно. еще раз спасибо