← Назад к вопросам
Будут ли равны 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]);
}
Выводы
- Объекты сравниваются по ссылке:
obj1 === obj2проверяет одну ли они ссылку - Для сравнения содержимого: используйте функции глубокого сравнения
- В React: будьте осторожны с созданием новых объектов в render
- Оптимизация: используйте useMemo для стабилизации объектов
- Библиотеки: lodash.isEqual или встроенные функции для сложных сравнений
Это фундаментальное отличие JavaScript и критично понимать при работе с состоянием и оптимизацией производительности.