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).