Статьи

Правда и Ложь: Когда в JavaScript не все равны

Переменные JavaScript свободно / динамически типизируются, и язык не заботится о том, как значение объявляется или изменяется.

JavaScript-truthy-falsy

2017.08.22: эта статья была обновлена, чтобы отразить текущее состояние экосистемы JavaScript.

let x;
x = 1;   // x is a number
x = '1'; // x is a string
x = [1]; // x is an array

Кажущиеся разными значения равны true==

 // all true
1 == '1';
1 == [1];
'1' == [1];

Более очевидный false===

 // all false
1 === '1';
1 === [1];
'1' === [1];

Внутренне JavaScript устанавливает значение одного из шести примитивных типов данных:

  • Не определено (переменная без определенного значения)
  • Null (одно нулевое значение)
  • Логическое (истинное или ложное)
  • Число (это включает в себя InfinityNaN
  • Строка (текстовые данные)
  • Symbol (уникальный и неизменный примитив, новый для ES6 / 2015)

Все остальное является объектом — включая массивы.

Правда и ложь

Как и тип, каждому значению также присуще логическое значение, обычно известное как истинное или ложное . Некоторые правила немного причудливы, поэтому понимание концепций и их влияние на сравнение помогают при отладке приложений JavaScript.

Следующие значения всегда ложны :

  • false
  • 0
  • ''""
  • null
  • undefined
  • NaN

Все остальное правдиво . Это включает:

  • '0'
  • 'false'
  • []
  • {}
  • function(){}

Поэтому в условиях может использоваться одно значение, например

 if (value) {
  // value is truthy
}
else {
  // value is falsy
  // it could be false, 0, '', null, undefined or NaN
}

Сравнение слабого равенства с ==

Неожиданные ситуации могут возникать при сравнении истинных и ложных значений с использованием ==

== true false 0 '' null undefined NaN Infinity [] {}
true правда ложный ложный ложный ложный ложный ложный ложный ложный ложный
false ложный правда правда правда ложный ложный ложный ложный правда ложный
0 ложный правда правда правда ложный ложный ложный ложный правда ложный
'' ложный правда правда правда ложный ложный ложный ложный правда ложный
null ложный ложный ложный ложный правда правда ложный ложный ложный ложный
undefined ложный ложный ложный ложный правда правда ложный ложный ложный ложный
NaN ложный ложный ложный ложный ложный ложный ложный ложный ложный ложный
Infinity ложный ложный ложный ложный ложный ложный ложный правда ложный ложный
[] ложный правда правда правда ложный ложный ложный ложный ложный ложный
{} ложный ложный ложный ложный ложный ложный ложный ложный ложный ложный

Правила:

  1. false
  2. nullundefined
  3. NaNвключая еще один NaN
  4. Infinityно ее нельзя сравнивать с truefalse
  5. Пустой массив — это правда, но сравнение с truefalsefalsetrue

Примеры:

 // 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. Избегайте прямых сравнений

Редко необходимо сравнивать два истинных и ложных значения, когда одно значение всегда будет равно true или false:

 // 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. Конвертировать в реальные логические значения, где это необходимо

Любое значение может быть преобразовано в реальное логическое значение с использованием двойного отрицания !! чтобы быть абсолютно уверенным, ложь генерируется только false0""nullundefinedNaN

 // instead of
if (x === y) // ...
// runs if x and y are identical...
// except when both are NaN

// use
if (!!x === !!y) // ...
// runs if x and y are identical...
// including when either or both are NaN

Вывод

Значения истина и ложь позволяют вам писать краткие условия JavaScript и троичные операторы. Однако всегда учитывайте крайние случаи. Мошеннический пустой массив или переменная NaN может привести к многим часам отладки горя!