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

В чем разница между значением и идентичностью?

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

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

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

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

Разница между значением (Value) и идентичностью (Identity)

Основная концепция

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

Примитивные типы — сравнение по значению

Для примитивов (number, string, boolean, null, undefined, symbol, bigint) сравнение происходит по значению:

// Строки — сравнение по значению
const str1 = 'hello';
const str2 = 'hello';

console.log(str1 === str2);      // true (одинаковые значения)
console.log(str1 == str2);       // true

// Числа — сравнение по значению
const num1 = 42;
const num2 = 42;

console.log(num1 === num2);      // true (одинаковые значения)
console.log(num1 == num2);       // true

// Boolean — сравнение по значению
const bool1 = true;
const bool2 = true;

console.log(bool1 === bool2);    // 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);              // { name: 'Alice', age: 30 }
console.log(obj2);              // { name: 'Alice', age: 30 }

// Но если они ссылаются на ОДИН объект
const obj3 = obj1;
console.log(obj1 === obj3);      // true (один и тот же объект в памяти)

// Массивы — то же самое
const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];

console.log(arr1 === arr2);      // false (разные массивы)
const arr3 = arr1;
console.log(arr1 === arr3);      // true (один и тот же массив)

Визуальная демонстрация

// ПРИМИТИВЫ: сравнение ПО ЗНАЧЕНИЮ
42 === 42           // true  - одинаковые значения
'text' === 'text'   // true  - одинаковые значения
true === true       // true  - одинаковые значения

// ОБЪЕКТЫ: сравнение ПО ИДЕНТИЧНОСТИ (по ссылке)
const user1 = { id: 1 };
const user2 = { id: 1 };
user1 === user2                 // false - разные объекты
user1 === user1                 // true  - один объект

const user3 = user1;
user1 === user3                 // true  - одна и та же ссылка

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

// Примитивы хранятся напрямую
const a = 10;
const b = 10;
// a и b содержат одно и то же значение 10
// a === b => true (одинаковые значения)

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

const obj3 = obj1;           // Адрес в памяти: 0x1000
// obj3 содержит ссылку на 0x1000
// obj1 === obj3 => true (одинаковые адреса)

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

Проблема с объектами в условиях:

const user1 = { name: 'Alice', age: 30 };
const user2 = { name: 'Alice', age: 30 };

if (user1 === user2) {
  console.log('Одинаковые пользователи');
} else {
  console.log('Разные пользователи');  // Выведется это!
}

// Решение: сравнивать по значению вручную
function usersEqual(u1, u2) {
  return u1.name === u2.name && u1.age === u2.age;
}

if (usersEqual(user1, user2)) {
  console.log('Одинаковые пользователи');  // Выведется это!
}

Проблема в массивах:

const data = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];

const newData = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];

console.log(data === newData);         // false (разные массивы)
console.log(JSON.stringify(data) === JSON.stringify(newData)); // true (одинаковые значения)

Решение: глубокое сравнение объектов

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)) return false;
    if (!deepEqual(obj1[key], obj2[key])) return false;
  }
  
  return true;
}

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

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

Использование Object.is()

Object.is() — это метод для сравнения, который работает как ===, но с некоторыми отличиями:

console.log(Object.is(1, 1));              // true
console.log(Object.is(NaN, NaN));          // true (!!! не как ===)
console.log(Object.is(+0, -0));            // false (!!! не как ===)

// Сравнение объектов — все равно по идентичности
const obj1 = { value: 1 };
const obj2 = { value: 1 };
console.log(Object.is(obj1, obj2));        // false

Современный подход: Lodash или встроенные методы

import { isEqual } from 'lodash';

const user1 = { name: 'Alice', age: 30 };
const user2 = { name: 'Alice', age: 30 };

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

В React и современном фронтенде

Это очень важно в React, где используются зависимости в хуках:

import { useEffect, useState } from 'react';

function Component() {
  const [data, setData] = useState({ count: 0 });
  
  // ПРОБЛЕМА: эффект срабатывает каждый раз
  useEffect(() => {
    console.log('Данные изменились');
  }, [data]);  // data — это объект, сравнивается по идентичности
  
  // РЕШЕНИЕ: сравнивать по значению
  useEffect(() => {
    console.log('Данные изменились');
  }, [data.count]);  // Сравниваем примитив, не объект
}

Ключевые выводы

  • Примитивы (number, string, boolean) сравниваются по значению: 5 === 5 будет true
  • Объекты и массивы сравниваются по идентичности (по ссылке): {} === {} будет false
  • === и == проверяют идентичность для объектов, не значение
  • Для сравнения объектов по значению нужно писать свой код или использовать библиотеки (lodash)
  • Это критично понимать при работе с React зависимостями и условиями