@vakalovaa

Почему при глубоком копировании объектов переполняется стек вызовов?

Задача:
Реализуйте и экспортируйте по умолчанию функцию, которая выполняет глубокое копирование объектов.

import cloneDeep from '../objects.js';
 
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

Для решения этой задачи, нужно последовательно обойти исходный объект и скопировать его данные в другой объект. Если значением какого-то свойства является объект, то нужно рекурсивно запустить реализованную функцию.

Подсказки
Для рекурсивного запуска понадобится имя для функции
_.isObject()
Object.entries()
Рекурсия
Для реализации этой задачи нельзя использовать функцию cloneDeep() библиотеки lodash.

Вот что я написала:

import isObject from 'lodash/isObject.js';
const cloneDeep = (obj) => {
  let result = {};
  const entries = Object.entries(obj);
  for (const entry of entries) {
    if (!isObject(entry)) {
      result = Object.assign(result, Object.fromEntries(entry));
    } else return cloneDeep(entry);
  } return result;
};
export default cloneDeep;
  • Вопрос задан
  • 225 просмотров
Решения вопроса 2
sergiks
@sergiks Куратор тега JavaScript
♬♬
Вероятно, клонируемый объект содержит циклические ссылки, типа
const a = {};
const b = {};
a.b = b;
b.a = a;

cloneDeep(a); // бесконечный цикл

Попробуйте подсмотреть реализацию cloneDeep() в loDash. В реале там вызывается baseClone()

Можно сохранять каждый обработанный ранее объект в Map – и проверять, не имели ли с ним уже дела ранее – тогда вместо изготовления ещё одной копии просто вставлять ранее сделанный клон.
Ответ написан
0xD34F
@0xD34F Куратор тега JavaScript
const entries = Object.entries(obj);
for (const entry of entries) {
  if (!isObject(entry)) {
    result = Object.assign(result, Object.fromEntries(entry));
  } else return cloneDeep(entry);

Что такое entries? - массив, состоящий из массивов.
Чем, соответственно, является entry? - массивом.
Что возвращает isObject для массивов? - true.
То есть, вне зависимости от содержимого конкретного entry произойдёт рекурсивный вызов.
Всё.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы