Truthy/falsy и сравнение объектов: почему {} !== {}

Что считается «истинным» и «ложным» и как сравнивать объекты, не наступив на грабли.

Falsy — значения, которые в логическом контексте превращаются в false. Всё остальное — truthy.

Ровно 8 falsy-значений

Их стоит просто запомнить: false, 0, -0, 0n (bigint-ноль), "" (пустая строка), null, undefined, NaN. Всё прочее истинно — включая пустой массив [] и пустой объект {}.

console.log(Boolean(0));
console.log(Boolean(""));
console.log(Boolean(null));
console.log(Boolean(NaN));
console.log(Boolean([]));   // пустой массив — ИСТИННЫЙ
console.log(Boolean({}));   // пустой объект — ИСТИННЫЙ
console.log(Boolean("0"));  // строка "0" — ИСТИННАЯ
console.log(Boolean("false"));

Вывод:

false
false
false
false
true
true
true
true

Частая ошибка новичков: проверять массив на «пустоту» через if (arr). Это всегда true, потому что массив — объект. Проверять нужно длину: if (arr.length).

Сравнение объектов: ссылки, а не содержимое

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

console.log({} === {});
console.log([] === []);
console.log({ a: 1 } === { a: 1 });

const x = { a: 1 };
const y = x;            // та же ссылка
console.log(x === y);

Вывод:

false
false
false
true

Как сравнить объекты по содержимому

Для простых случаев (без функций, без вложенных Date, без циклов) подойдёт сравнение сериализованных строк. Это не универсально, но на собеседовании показывает понимание сути.

const a = { name: "Аня", age: 30 };
const b = { name: "Аня", age: 30 };

console.log(a === b);
console.log(JSON.stringify(a) === JSON.stringify(b));

Вывод:

false
true

Важная оговорка для собеседования: JSON.stringify зависит от порядка ключей и не видит undefined, функции, Symbol. Для надёжного «глубокого равенства» в реальном коде берут готовую функцию (например, isEqual из lodash).

Итог

  • Falsy ровно восемь; [] и {} — истинные.
  • === сравнивает объекты по ссылке, поэтому {} !== {}.
  • Сравнение по содержимому — отдельная задача (сериализация или deep-equal).
Проверьте себя
1. Какое из значений является truthy (истинным)?
A0
B"" (пустая строка)
C[] (пустой массив)
DNaN
2. Что выведет console.log({a:1} === {a:1})?
Atrue
Bfalse
Cundefined
DОшибку
3. Как корректно сравнить два простых объекта по содержимому?
AЧерез ===
BЧерез ==
CСравнить JSON.stringify(a) === JSON.stringify(b)
DОбъекты сравнить нельзя никак
Поддержать проект