Значения Falsey в JavaScript

Сегодня у меня был интересный вопрос, который немного меня насторожил. Меня спрашивали о ложных ценностях. Итак, undefined, NaN, null, 0 и пустая строка оцениваются как false. По какой причине это полезно знать в JavaScript? Единственное, о чем я могу думать, - это не делать этого:

if (mystring === '' || mystring === undefined) { }

Я могу это сделать:

if (!mystring)

Это единственное полезное приложение?

Ответ 1

Одна опасная проблема значений ложных данных, о которых вы должны знать, - это проверка наличия определенного свойства.

Предположим, что вы хотите проверить наличие нового свойства; когда это свойство может иметь значение 0 или "", вы не можете просто проверить его доступность, используя

if (!someObject.someProperty)
    /* incorrectly assume that someProperty is unavailable */

В этом случае вы должны проверить, действительно ли он присутствует или нет:

if (typeof someObject.someProperty == "undefined")
    /* now it really not available */

Также имейте в виду, что NaN не равно ничему, даже не самому себе (NaN != NaN).

Ответ 2

В JavaScript есть две отдельные проблемы с значениями "falsey".

Во-первых, есть официальная схема конверсии, которая возвращает Boolean (x). Это возвращает false, когда x является ложным или 0 или NaN, или null или undefined или "", и true в противном случае. Это то же поведение, что и

if (condition) {/*true path*/} else {/*false path*/}

то есть ложный путь выполняется, если Boolean (condition) вернул false и истинный путь будет выполнен иначе. Это поведение часто используется, чтобы проверить, определено ли свойство. Однако выполнение этого небезопасно, если вы не уверены, что это свойство будет объектом или массивом, если он определен. Самый безопасный способ проверить, определено ли свойство, - сделать

if (property != null) { /*property is defined*/} 

который гарантирует, что свойство не равно null или undefined. Если вы хотите убедиться, что свойство не undefined do

if (property !== undefined) { /*property is not undefined (but may be null)*/ } 

(обратите внимание на extra = in! ==).

Во-вторых, есть все значения, которые == false. Это все, что может быть принуждено к 0 (к чему принуждается ложь). Это включает в себя все значения, которые преобразуются в false, кроме NaN (который не может == false в силу этого никогда никого), null и undefined. Но он также включает все объекты, которые при преобразовании в строку и затем преобразованные в число равны 0. Например, это включает в себя все, что при преобразовании в строку является либо пустой строкой "или" 0 ", либо" -0 "или" +0 "или" 0x00 "или" 000 "или" 0e0 "или" 0,0000 "...., например,

({toString: function() {return "-00.0e000";}}) == false

истинно. Интересно, что это включает в себя пустой массив и любую вложенность массивов, содержащих только один другой элемент, который возвращает пустую или 0 строку, поскольку массивы, отображаемые как строки, показывают только содержимое без окружающих скобок. То есть

[[[[0]]]] == false; // Because [[[[0]]]].toString() === "0"
[] == false;
[[[""]]] == false;
["0"] == false;
[[({toString: function() {return "0";}})]] == false;

Полный алгоритм вычисления == false описан здесь.

Причина в том, что это может быть связано с тем, что это может привести к тонким, трудным для поиска ошибкам, если вы не понимаете большинство этих правил. Наиболее важные выходы, вероятно, связаны с тем, как работает if (condition) и что использование === позволяет избежать большинства других сумасшедших вещей.

Ответ 3

Важно понять, как это работает в JS, поэтому вы не удивлены. Не обязательно то, что ложно, но то, что правдиво и как они сравниваются друг с другом.

Одним из примеров является то, что '0' считается равным 0 с ==, но он не равен '' - хотя 0. Сравнение JavaScript не всегда транзитивно.

Таким образом, это означает, что только потому, что (foo==bar && bar==fizz) истинно, (foo==fizz) не всегда истинно. Чтобы перейти с приведенным выше примером, '0' == 0 и 0 == '', но '0'!= '' - потому что вы сравниваете строки в последнем экземпляре, поэтому их сравнивают как строки и не принуждают к номерам.

Ответ 4

Полезно определить, имеет ли браузер определенные предопределенные объекты:

if(!!navigator.geolocation){
  // executes if the browser has geolocation support
}

if(!!document.createElement('canvas').getContext){
  // executes if the browser supports <canvas>
}

Объяснение: navigator.geolocation - это объект или undefined. В случае, если объект !navigator.geolocation вернет false, если он undefined, он вернет true. Таким образом, чтобы проверить, включен ли браузер в геолокации, вы хотите снова "перевернуть" логическое значение, добавив еще один !.

Ответ 5

Важно знать, что 0 оценивает false, чтобы предотвратить выполнение таких действий, как:

if(str.indexOf('foo'))

Ответ 6

Они также полезны для установки значений по умолчанию...

function foo(bar){
    alert(bar || "default");
}

Я знаю, что многие люди пытаются сделать

if (typeof(foo) === "undefined"){}

чтобы обойти фальшивость, но у этого были свои проблемы, потому что

typeof(null) === "object"

по какой-то причине