> Можно ли сравнить два объекта в JavaScript и как это сделать (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Soft_Media_Group, Tilda, Evercode

Стек: JavaScript

> Пример ответа

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

Да, можно, но в JavaScript нет встроенного метода для глубокого сравнения объектов. Операторы == и === сравнивают объекты по ссылке, а не по содержимому. Для сравнения по значению нужно реализовать собственную логику: сериализовать в JSON (с ограничениями) или написать рекурсивную функцию, которая обходит ключи и сравнивает значения, включая вложенные объекты и массивы.

Подробное объяснение

В JavaScript объекты - ссылочный тип данных. При сравнении через == или === проверяется, указывают ли обе переменные на один и тот же участок памяти, а не на идентичность структуры и значений. Это фундаментальное поведение языка.

Для сравнения по содержимому (deep equality) есть несколько подходов:

  • JSON.stringify: быстрый, но не учитывает функции, undefined, Symbol, NaN (превращается в null), циклические ссылки (вызовет ошибку), порядок ключей (важен для JSON).
  • Рекурсивное сравнение: полный контроль, но нужно обрабатывать все типы: примитивы, объекты, массивы, Date, RegExp, Map, Set, циклические ссылки, прототипы.
  • Библиотеки: lodash _.isEqual, Ramda R.equals - проверенные решения для продакшена.

Важно понимать trade-off: производительность (глубокое сравнение может быть дорогим для больших объектов) и корректность (не все реализации одинаково обрабатывают краевые случаи).

На практике

В реальных проектах чаще всего используют готовые утилиты, например lodash.isEqual. Если проект маленький и нет зависимостей, пишут простую рекурсивную функцию, но с ограничениями. Для React-приложений глубокое сравнение может понадобиться в useEffect или useMemo для определения изменений пропсов, но обычно достаточно поверхностного сравнения через Object.is или shallowEqual.

Избегайте JSON.stringify для сравнения в продакшене - он ненадёжен для данных с функциями, undefined или циклическими ссылками. Если используете, документируйте ограничения.

Пример кода

JAVASCRIPT
// Простая рекурсивная реализация (без поддержки Map, Set, циклических ссылок)
function deepEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (typeof a !== typeof b) return false;
if (typeof a !== 'object') return a === b;
// Date
if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime();
}
// RegExp
if (a instanceof RegExp && b instanceof RegExp) {
return a.toString() === b.toString();
}
// Arrays
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) return false;
return a.every((val, idx) => deepEqual(val, b[idx]));
}
// Objects
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
return keysA.every(key => deepEqual(a[key], b[key]));
}
// Использование
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };
console.log(deepEqual(obj1, obj2)); // true

Как отвечать на собеседовании

Начните с того, что прямое сравнение через === не работает по содержимому, объясните причину (ссылочный тип). Затем перечислите подходы: JSON, рекурсия, библиотеки. Обязательно упомяните ограничения каждого: JSON не видит функции и undefined, рекурсия требует обработки краевых случаев. Покажите понимание производительности и типичных ошибок. Если спросят про Object.is - скажите, что это аналог === для примитивов, не для объектов.

Что проверяет интервьюер

  • Понимание ссылочной модели JavaScript и разницы между сравнением по ссылке и по значению.
  • Знание встроенных механизмов и их ограничений.
  • Умение писать или выбирать корректное решение с учётом краевых случаев (циклические ссылки, специальные объекты).
  • Практический опыт: когда использовать готовые библиотеки, а когда писать своё.

Типичные ошибки

  • Использовать JSON.stringify без оговорок, не зная про undefined, функции, NaN, циклические ссылки.
  • Писать рекурсивную функцию, не обрабатывая null, Date, RegExp, массивы.
  • Забывать про порядок ключей в JSON.stringify (он не гарантирован, хотя на практике обычно совпадает).
  • Сравнивать объекты через == или === и ожидать сравнения по содержимому.
  • Не учитывать производительность для глубоко вложенных или больших объектов.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью