← Назад к вопросам

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

1.3 Junior🔥 82 комментариев
#JavaScript Core#React

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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

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

Принцип сравнения по ссылке

Когда вы создаёте объект, переменная хранит не сам объект, а ссылку на область памяти, где он расположен. При сравнении == или === проверяется, ссылаются ли переменные на один и тот же объект в памяти.

const obj1 = { name: 'John' };
const obj2 = { name: 'John' };
const obj3 = obj1;

console.log(obj1 === obj2); // false — разные объекты в памяти
console.log(obj1 === obj3); // true — obj3 ссылается на obj1
console.log(obj1 == obj2);  // false — то же самое для ==

Даже если obj1 и obj2 имеют идентичные поля, это два независимых объекта. Для === они различны, так как их ссылки не совпадают.

Особенности операторов == и ===

  • === (строгое равенство): проверяет идентичность ссылок. Не приводит типы.
  • == (нестрогое равенство): может приводить типы (например, число к строке), но для объектов всё равно сравнивает ссылки.
const arr1 = [1, 2];
const arr2 = [1, 2];
const arr3 = arr1;

console.log(arr1 === arr2); // false
console.log(arr1 === arr3); // true
console.log(arr1 == '1,2'); // true — из-за приведения массива к строке!

В последнем случае arr1 == '1,2' даёт true, потому что массив приводится к строке '1,2'. Это показывает ещё одну проблему == — непредсказуемое приведение типов.

Как правильно сравнивать объекты?

Для сравнения объектов по содержимому нужно реализовать глубокое сравнение:

  1. Простые случаи: если объекты имеют простую структуру, можно сравнить их JSON-представление (но это не работает для полей с undefined, функциями или циклическими ссылками).
const obj1 = { a: 1, b: 'text' };
const obj2 = { a: 1, b: 'text' };
console.log(JSON.stringify(obj1) === JSON.stringify(obj2)); // true
  1. Глубокое сравнение: использовать готовые библиотечные функции (например, _.isEqual из Lodash) или написать свою рекурсивную функцию.
// Пример простой функции для неглубокого сравнения
function shallowEqual(obj1, obj2) {
  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);
  if (keys1.length !== keys2.length) return false;
  return keys1.every(key => obj1[key] === obj2[key]);
}
  1. Для React-приложений: часто используется сравнение через JSON.stringify или хеширование для определения изменений в пропсах.

Исключения и нюансы

  • Примитивные типы (строки, числа, булевы значения) сравниваются по значению.
  • Специальные значения: NaN === NaN возвращает false, null == undefined возвращает true.
  • Встроенные объекты: разные экземпляры new Date('2023-01-01') не будут равны через ===.

Выводы

Использование == или === для сравнения объектов в JavaScript оправдано только при проверке, являются ли две переменные ссылкой на один объект. Для сравнения содержимого объектов необходимы специальные методы, учитывающие их структуру и типы данных полей. Это поведение — следствие реализации языка, где объекты являются ссылочными типами, и оно характерно для многих языков программирования (например, Java, Python).