Сравнение двух вещей на предмет равенства часто может сбить с толку неосторожного разработчика JavaScript, поскольку у языка есть несколько особенностей, о которых нам нужно знать.
В этой статье мы рассмотрим, почему это так, исследуя операторы двойного и тройного равенства, а также концепцию истинных и ложных значений в JavaScript. К тому времени, когда вы закончите читать, вы поймете, как JavaScript выполняет сравнения, а также как истинные и ложные значения могут помочь вам писать более чистый код.
Правда и ложь: когда в JavaScript не все равны
Ввод в JavaScript
Переменные JavaScript свободно/динамически типизированы, и язык не заботится о том, как объявляется или изменяется значение:
let x;
x = 1; // x is a number
x = '1'; // x is a string
x = [1]; // x is an array
Кажущиеся разными значениями приравниваются trueпри сравнении с == (свободное или абстрактное равенство), потому что JavaScript (эффективно) преобразует каждое из них в строковое представление перед сравнением:
// all true
1 == '1';
1 == [1];
'1' == [1];
Правда и ложь: когда в JavaScript не все равны
Более очевидный falseрезультат получается при сравнении с === (строгое равенство), потому что рассматривается тип:
// all false
1 === '1';
1 === [1];
'1' === [1];
Внутри JavaScript устанавливает значение одного из семи примитивных типов данных:
Undefined (переменная без определенного значения)
Null (одно нулевое значение)
Логическое значение (a trueили falseзначение)
Номер (сюда входит Infinityи NaN— не номер!)
BigInt (целочисленное значение больше 2⁵³ — 1)
Строка (текстовые данные)
Символ (уникальный и неизменяемый примитив, новый для ES6/2015)
Все остальное является объектом, включая массивы.
Правда и ложь: когда в JavaScript не все равны
Истинные и ложные значения в JavaScript
Помимо типа, каждое значение также имеет неотъемлемое логическое значение, обычно известное как truey или false. Некоторые правила, которые определяют, как небулевы значения преобразуются в истинные или ложные значения, немного странные. Понимание концепций и их влияния на сравнение помогает при отладке приложений JavaScript.
Следующие значения всегда ложны:
false
0 (нуль)
-0 (минус ноль)
0n (BigIntноль)
'', «», `` (пустая строка)
null
undefined
NaN
Все остальное правда. Это включает:
'0' (строка, содержащая один ноль)
'false’ (строка, содержащая текст «false»)
[] (пустой массив)
{} (пустой объект)
function () {} («пустая» функция)
Таким образом, в условиях можно использовать одно значение. Например:
if (value) {
// value is truthy
}
else {
// value is falsy
// it could be false, 0, '', null, undefined or NaN
}
document.all
Вы также можете увидеть document.allв списке ложное значение. Это возвращает элемент, HTMLAllCollectionкоторый содержит список всех элементов документа. И хотя это рассматривается falseв логическом контексте, это устаревшая функция, и MDN не рекомендует ее использовать.
Правда и ложь: когда в JavaScript не все равны
Свободное сравнение равенства с==
Неожиданные ситуации могут возникнуть при сравнении истинных и ложных значений с использованием нестрогого ==равенства:
== true false 0 '' null undefined NaN Infinity [] {}
true истинный ложный ложный ложный ложный ложный ложный ложный ложный ложный
false ложный истинный истинный истинный ложный ложный ложный ложный истинный ложный
0 ложный истинный истинный истинный ложный ложный ложный ложный истинный ложный
'' ложный истинный истинный истинный ложный ложный ложный ложный истинный ложный
null ложный ложный ложный ложный истинный истинный ложный ложный ложный ложный
undefined ложный ложный ложный ложный истинный истинный ложный ложный ложный ложный
NaN ложный ложный ложный ложный ложный ложный ложный ложный ложный ложный
Infinity ложный ложный ложный ложный ложный ложный ложный истинный ложный ложный
[] ложный истинный истинный истинный ложный ложный ложный ложный ложный ложный
{} ложный ложный ложный ложный ложный ложный ложный ложный ложный ложный
Правила:
false, нулевые и пустые строки эквивалентны.
nullи undefinedэквивалентны сами себе и друг другу, но ничему другому.
NaNне эквивалентен ничему — в том числе другому NaN!.
Infinityправдиво — но его нельзя сравнивать с trueили false!.
Пустой массив правдив — но сравнение с trueis falseи сравнение с falseis true?!.
Обратите внимание на разницу в том, как могут оцениваться пустые значения разных типов. Пустая строка или undefinedзначение являются ложными, но пустой массив или объект являются истинными.
Примеры:
// all true
false == 0;
0 == '';
null == undefined;
[] == false;
!![0] == true;
// all false
false == null;
NaN == NaN;
Infinity == true;
[] == true;
[0] == true;
Строгое сравнение равенства с===
Ситуация проясняется при использовании сравнения строго на равенство, поскольку типы значений должны совпадать:
=== true false 0 '' null undefined NaN Infinity [] {}
true истинный ложный ложный ложный ложный ложный ложный ложный ложный ложный
false ложный истинный ложный ложный ложный ложный ложный ложный ложный ложный
0 ложный ложный истинный ложный ложный ложный ложный ложный ложный ложный
'' ложный ложный ложный истинный ложный ложный ложный ложный ложный ложный
null ложный ложный ложный ложный истинный ложный ложный ложный ложный ложный
undefined ложный ложный ложный ложный ложный истинный ложный ложный ложный ложный
NaN ложный ложный ложный ложный ложный ложный ложный ложный ложный ложный
Infinity ложный ложный ложный ложный ложный ложный ложный истинный ложный ложный
[] ложный ложный ложный ложный ложный ложный ложный ложный ложный ложный
{} ложный ложный ложный ложный ложный ложный ложный ложный ложный ложный
Единственным исключением является NaN, который упорно остается неэквивалентным всему.
Рекомендации по работе с истинными или ложными значениями
Истинные и ложные значения могут подловить самых опытных разработчиков. У новичков в программировании или переходе с других языков нет шансов! К счастью, есть три простых шага для выявления наиболее трудно обнаруживаемых ошибок при работе с истинными и ложными переменными. Давайте рассмотрим каждый по очереди.
1. Избегайте прямых сравнений
Редко бывает необходимо сравнивать два истинных и ложных значения, когда одно значение всегда будет равняться истинному или ложному:
// instead of
if (x == false) //...
// runs if x is false, 0, '', or []
// use
if (! x) //...
// runs if x is false, 0, '', NaN, null or undefined
2. Используйте ===строгое равенство
Используйте ===строгое сравнение на равенство (или≠=строгое неравенство), чтобы сравнивать значения и избегать проблем с преобразованием типов:
// instead of
if (x == y) //...
// runs if x and y are both truthy or both falsy
// e.g. x = null and y = undefined
// use
if (x === y) //...
// runs if x and y are identical...
// except when both are NaN
3. При необходимости преобразовать в реальные логические значения.
Вы можете преобразовать любое значение в настоящее логическое значение в JavaScript, используя либо логический конструктор, либо двойное отрицание!!. Это позволит вам быть абсолютно уверенным, что false генерируется только false, 0, «», nullи: undefinedNaN
// instead of
if (x === y) //...
// runs if x and y are identical...
// except when both are NaN
// use
if (Boolean (x) === Boolean (y)) //...
// or
if (!! x ===!! y) //...
// runs if x and y are identical...
// including when either or both are NaN
Конструктор Booleanвозвращает trueзначение при передаче истинного значения и возвращает falseпри передаче ложного значения. Это может быть полезно в сочетании с итерационным методом. Например:
const truthy_values = [
false,
0,
``,
'',
«»,
null,
undefined,
NaN,
'0',
'false’,
[],
{},
function () {}
].filter (Boolean) ;
// Filter out falsy values and log remaining truthy values
console.log (truthy_values) ;
Заключение
Истинные и ложные значения позволяют вам писать краткие условия JavaScript и тернарные операторы. Однако всегда учитывайте крайние случаи. Мошеннический пустой массив или переменная NaN могут привести к многочасовой отладке!
Вам нужна помощь с