Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про JavaScript: deep equal, object comparison, recursion, JavaScript, strict equality

Как реализовать глубокое сравнение объектов (deep equal)?

Вопрос проверяет понимание рекурсивного сравнения объектов и массивов, включая вложенные структуры, что необходимо для корректной работы с состоянием и тестированием.

Короткий ответ

Глубокое сравнение объектов — это рекурсивная проверка на равенство всех свойств двух объектов, включая вложенные объекты и массивы. В отличие от простого сравнения (== или ===), которое для объектов проверяет ссылки, deep equal сравнивает фактические значения. Базовый алгоритм: проверяем типы, если это примитивы — сравниваем через ===, если это объекты — рекурсивно сравниваем их ключи и значения. Важно обрабатывать крайние случаи: null, Date, RegExp, циклические ссылки.

Длинный ответ

Глубокое сравнение (deep equal) — это операция, которая определяет, идентичны ли два объекта по структуре и значению всех их свойств, включая вложенные объекты и массивы. Это фундаментальная задача в JavaScript, так как стандартные операторы равенства (==, ===) для объектов сравнивают лишь ссылки, а не содержимое.

Основной алгоритм

Алгоритм обычно реализуется рекурсивно и включает следующие шаги:

  • Сравнить типы операндов. Если типы разные, объекты не равны.
  • Если оба операнда — примитивы (или null/undefined), использовать строгое равенство (===).
  • Если оба — объекты (включая массивы):
    1. Проверить, являются ли они одним и тем же объектом (ссылочное равенство) — это ускоряет проверку.
    2. Сравнить количество ключей (свойств). Если разное, объекты не равны.
    3. Для каждого ключа рекурсивно вызвать deep equal для значений.

Особые случаи и оптимизации

Наивная реализация может столкнуться с проблемами:

  • Циклические ссылки: объект ссылается на себя через цепочку свойств. Необходимо отслеживать уже посещённые пары объектов, чтобы избежать бесконечной рекурсии (например, с помощью WeakMap).
  • Специальные объекты: Date, RegExp, Map, Set требуют особого сравнения (например, для Date сравнивать timestamp).
  • Производительность: для больших объектов рекурсия может быть глубокой; иногда полезно сначала сравнить простые свойства.

Пример реализации (базовый, без обработки всех крайних случаев)

function deepEqual(obj1, obj2) {
  // Сравнение примитивов и ссылок
  if (obj1 === obj2) return true;
  
  // Проверка типов
  if (typeof obj1 !== 'object' || obj1 === null ||
      typeof obj2 !== 'object' || obj2 === null) {
    return false;
  }
  
  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);
  
  if (keys1.length !== keys2.length) return false;
  
  for (let key of keys1) {
    if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {
      return false;
    }
  }
  return true;
}

// Пример использования
const a = { x: 1, y: { z: 2 } };
const b = { x: 1, y: { z: 2 } };
console.log(deepEqual(a, b)); // true
console.log(deepEqual(a, { x: 1, y: { z: 3 } })); // false

В реальных проектах часто используют готовые библиотечные функции, такие как _.isEqual из Lodash, которые тщательно обрабатывают все крайние случаи.

Вывод: Глубокое сравнение необходимо при работе с неизменяемым состоянием (например, в Redux), для написания тестов или при сравнении конфигурационных объектов. Для простых случаев можно написать свою функцию, но в продакшене надёжнее использовать проверенные библиотеки.

Уровень

  • Рейтинг:

    4

  • Сложность:

    5

Навыки

  • JavaScript

    JavaScript

Ключевые слова

#deep equal

#object comparison

#recursion

#JavaScript

#strict equality

Подпишись на React Developer в телеграм