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

Будут ли равны 2 одинаковых объекта, если они не ссылаются друг на друга

1.0 Junior🔥 211 комментариев
#JavaScript Core

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Сравнение объектов в JavaScript

Ответ: Нет, два идентичных объекта будут НЕ равны, если они не ссылаются на один и тот же объект в памяти. JavaScript сравнивает объекты по ссылке (reference equality), а не по содержимому (value equality).

Сравнение по ссылке vs по значению

Примитивные типы (по значению):

console.log(5 === 5);              // true (одинаковое значение)
console.log("hello" === "hello");   // true (одинаковое значение)
console.log(true === true);         // true (одинаковое значение)

Объекты (по ссылке):

const obj1 = { name: "Alice", age: 30 };
const obj2 = { name: "Alice", age: 30 };

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

Как это работает в памяти

const obj1 = { name: "Alice" };
const obj2 = { name: "Alice" };
const obj3 = obj1;

// В памяти:
// obj1 -> ссылка на объект #100: { name: "Alice" }
// obj2 -> ссылка на объект #200: { name: "Alice" }  (другой объект!)
// obj3 -> ссылка на объект #100: { name: "Alice" }   (та же ссылка что obj1)

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

Практический пример

// ❌ Не работает
const user1 = { id: 1, name: "Bob" };
const user2 = { id: 1, name: "Bob" };

if (user1 === user2) {
  console.log("Это одинаковые пользователи");
} else {
  console.log("Это разные объекты"); // <- Выполнится
}

// ✅ Работает
const user3 = user1;

if (user1 === user3) {
  console.log("Это одна и та же ссылка"); // <- Выполнится
}

Почему так работает?

В памяти JavaScript:

Значения примитивов хранятся напрямую:
const a = 5;     // 5 находится в переменной a
const b = 5;     // 5 находится в переменной b
a === b          // true (одно и то же значение)

Объекты хранятся по ссылке:
const obj1 = { x: 5 };  // объект в памяти по адресу 0x1000, obj1 содержит адрес
const obj2 = { x: 5 };  // объект в памяти по адресу 0x2000, obj2 содержит адрес
obj1 === obj2           // false (разные адреса)

Способы сравнения объектов

Способ 1: Ручное сравнение свойств

function objectsEqual(obj1, obj2) {
  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);
  
  if (keys1.length !== keys2.length) {
    return false;
  }
  
  for (let key of keys1) {
    if (obj1[key] !== obj2[key]) {
      return false;
    }
  }
  
  return true;
}

const user1 = { id: 1, name: "Alice" };
const user2 = { id: 1, name: "Alice" };

console.log(objectsEqual(user1, user2)); // true
console.log(user1 === user2);            // false

Способ 2: JSON.stringify (для простых объектов)

const obj1 = { name: "Alice", age: 30 };
const obj2 = { name: "Alice", age: 30 };

if (JSON.stringify(obj1) === JSON.stringify(obj2)) {
  console.log("Объекты идентичны");
}

// Но это медленнее и может быть ненадежно
// Проблемы с порядком ключей:
const obj3 = { age: 30, name: "Alice" };
console.log(JSON.stringify(obj1) === JSON.stringify(obj3)); // false!

Способ 3: Глубокое сравнение (lodash)

import { isEqual } from lodash;

const obj1 = { name: "Alice", address: { city: "NYC" } };
const obj2 = { name: "Alice", address: { city: "NYC" } };

console.log(isEqual(obj1, obj2)); // true (глубокое сравнение)

Способ 4: Встроенная функция для структурированного клонирования

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 false;
  
  const keys = Object.keys(a);
  
  if (keys.length !== Object.keys(b).length) return false;
  
  for (let key of keys) {
    if (!deepEqual(a[key], b[key])) return false;
  }
  
  return true;
}

const obj1 = { name: "Alice", address: { city: "NYC" } };
const obj2 = { name: "Alice", address: { city: "NYC" } };

console.log(deepEqual(obj1, obj2)); // true

Частая ошибка в React

// ❌ Проблема: объект создается заново каждый раз
function UserCard() {
  const style = { color: "red", fontSize: "16px" };
  
  return <div style={style}>Профиль</div>;
}

// Каждый раз при ререндере создается новый объект style
// Если передать style в дочерний компонент, он тоже ререндерится

// ✅ Решение 1: Вынести за компонент
const STYLE = { color: "red", fontSize: "16px" };

function UserCard() {
  return <div style={STYLE}>Профиль</div>;
}

// ✅ Решение 2: Использовать useMemo
function UserCard() {
  const style = useMemo(() => ({
    color: "red",
    fontSize: "16px"
  }), []);
  
  return <div style={style}>Профиль</div>;
}

// ✅ Решение 3: Использовать CSS классы
function UserCard() {
  return <div className="user-card">Профиль</div>;
}

.user-card {
  color: red;
  font-size: 16px;
}

Сравнение массивов (то же правило)

const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];

console.log(arr1 === arr2);  // false (разные ссылки)

// Для сравнения содержимого:
console.log(JSON.stringify(arr1) === JSON.stringify(arr2)); // true

// Или:
function arraysEqual(a, b) {
  return a.length === b.length && a.every((val, idx) => val === b[idx]);
}

console.log(arraysEqual(arr1, arr2)); // true

Таблица типов сравнения

Тип===СравнениеПример
number==значение5 === 5 (true)
string==значение"hi" === "hi" (true)
boolean==значениеtrue === true (true)
null==значениеnull === null (true)
undefined==значениеundefined === undefined (true)
objectпо ссылкеадрес памяти{a:1} === {a:1} (false)
arrayпо ссылкеадрес памяти[1,2] === [1,2] (false)
functionпо ссылкеадрес памятиfn1 === fn1 (true если одна функция)

Практическое применение

Проверка изменений в React

function Component({ user }) {
  const prevUserRef = useRef(null);
  
  useEffect(() => {
    // Это НЕ сработает для объектов!
    if (user === prevUserRef.current) {
      console.log("Пользователь не изменился");
    } else {
      console.log("Пользователь изменился");
    }
    
    prevUserRef.current = user;
  }, [user]);
}

// Для правильного сравнения:
function Component({ user }) {
  const prevUserRef = useRef(null);
  
  useEffect(() => {
    if (deepEqual(user, prevUserRef.current)) {
      console.log("Пользователь не изменился");
    } else {
      console.log("Пользователь изменился");
    }
    
    prevUserRef.current = user;
  }, [user]);
}

Выводы

  1. Объекты сравниваются по ссылке: obj1 === obj2 проверяет одну ли они ссылку
  2. Для сравнения содержимого: используйте функции глубокого сравнения
  3. В React: будьте осторожны с созданием новых объектов в render
  4. Оптимизация: используйте useMemo для стабилизации объектов
  5. Библиотеки: lodash.isEqual или встроенные функции для сложных сравнений

Это фундаментальное отличие JavaScript и критично понимать при работе с состоянием и оптимизацией производительности.

Будут ли равны 2 одинаковых объекта, если они не ссылаются друг на друга | PrepBro