Правильность написания функции
Есть задача
Реализуйте и экспортируйте по умолчанию функцию, которая выполняет глубокое копирование объектов.
const data = {
key: 'value',
key2: {
key: 'innerValue',
innerKey: {
anotherKey: 'anotherValue',
},
},
};
И условие для проверки:
// result имеет такую же структуру, как и data
const result = cloneDeep(data);
// Но внутри другие объекты
result.key2 !== data.key2; // true
result.key2.innerKey !== data.key2.innerKey; // true
Решение
const data = {
key: 'value',
key2: {
key: 'innerValue',
innerKey: {
anotherKey: 'anotherValue',
},
},
};
const cloneDeep = obj => {
const clone = {};
const values = Object.values(obj);
for (const value of values) {
if ((typeof value) === 'object') {
Object.assign(clone, obj);
cloneDeep(value);
} else {
Object.assign(clone, obj);
}
}
return clone;
}
const result = cloneDeep(data);
console.log(result);
То есть я получаю полностью изолированный объект, изменяя значение в полученном, не затрагивая в исходном.
Но при проверке условий получаю "false". Или же стоит воспринимать буквально "Но внутри другие объекты"?. При изменении значений соответственно получаю "true".
Ответы (1 шт):
Приведенная функция cloneDeep НЕ делает глубокое копирование. По сути ее вызов сводится к одному вызову Object.assign.
Клонированный объект возвращается с помощью return, однако возвращаемое значение игнорируется всегда, кроме самого первого вызова.
Вместо этого, оно должно было записываться по указанному ключу в объекте-клоне.
Кроме того typeof obj === 'object' не охватывает, например, функции, которые в этом случае не копируются, а продолжают по ссылке передаваться.
Также ломаются сложные объекты, вроде массивов, сетов, и т.д. так как клон - это всегда обычный объект.
Для простого случая, когда игнорируются сложные классы объектов, алгоритм может быть следующим:
- если передали не объект - возвращаем как есть
- создаем пустой объект-клон
- для каждого клюя в исходном объекте присваиваем значением глубокую копию значения из исходного объекта.
Пример:
const data = {
key: 'value',
key2: {
key: 'innerValue',
innerKey: {
anotherKey: 'anotherValue',
},
},
};
const cloneDeep = obj => {
if (!obj || typeof obj !== 'object') return obj;
const clone = {};
const entries = Object.entries(obj);
for (const [key, val] of entries) {
clone[key] = cloneDeep(val);
}
return clone;
}
const result = cloneDeep(data);
console.log(result);
// Но внутри другие объекты
console.log(result.key2 !== data.key2); // true
console.log(result.key2.innerKey !== data.key2.innerKey); // true