Выбор ответа Senior Реализация с нуля обновлено

deepClone падает на циклической ссылке

Вопрос

Функция падает на объекте o, где o.self = o. Какое исправление верное?

function deepClone(value, seen = new WeakMap()) {
  if (value === null || typeof value !== 'object') return value;
  if (seen.has(value)) return seen.get(value);
  const copy = Array.isArray(value) ? [] : {};
  for (const key of Object.keys(value)) {
    copy[key] = deepClone(value[key], seen);
  }
  seen.set(value, copy);
  return copy;
}

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: Перенести seen.set(value, copy) до цикла по ключам. Копия регистрируется в seen только после обхода всех ключей.

Варианты ответа

  1. Перенести seen.set(value, copy) до цикла по ключамправильный ответ
  2. Заменить WeakMap на Map, чтобы ссылка на o не терялась
  3. Заменить Object.keys на for...in, чтобы обход шёл лениво
  4. Проверять seen.has(value) после цикла по ключам, а не до него

Разбор

Копия регистрируется в seen только после обхода всех ключей. Когда рекурсия доходит до o.self, в seen ещё пусто, и функция снова начинает копировать o, уходя в бесконечную рекурсию до RangeError. Если записать пару в seen сразу после создания copy, повторная встреча вернёт уже создаваемую копию, и цикл замкнётся правильно. Тип словаря и способ перебора ключей на проблему не влияют, а проверка после цикла бессмысленна.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.