Разница между Boolan (! X) и Boolean (x == 0)?

Код-фрагмент 1:

if ( !x ) { /* do stuff */ }

Код-фрагмент 2:

if ( x == 0 ) { /* do stuff */ }

Для каких значений x эти два фрагмента кода отличаются?

Я спрашиваю, потому что, хотя я читал главу в == в спецификации, мне все еще трудно справляться с ситуациями, подобными приведенным выше (там, где они объединены с ToBoolean принуждением).

btw, я хочу знать это только ради того, чтобы знать это (я хочу понять язык), поэтому не беспокойтесь, рассказывая мне о === или спрашивая меня, что такое x.

Обновление: Я исправил фрагмент кулака. Я имел в виду !x.

Ответ 1

Следующее даст вам true для первого и false для второго фрагмента:

  • NaN
  • null
  • undefined

И это даст вам false для первого и true для второго фрагмента:

  • []
  • "0" и любая другая строка, которая преобразуется в 0 с помощью Number(x), таких как "00", "000", "+0" и "-0" (которые я теперь буду называть "строк noughty" )
  • массив, содержащий один элемент, который является 0, null, undefined или пустая или нулевая строка.

Для всего остального вы получите тот же результат для обоих фрагментов, хотя может быть один или два других случая, о которых я не думал.

Ответ 2

  • [] == 0 истинно; ![] false
  • null == 0 - false; !null истинно
  • NaN == 0 - false; !NaN истинно
  • undefined == 0 - false; !undefined истинно

!x проверяет, является ли x "ложным".
x == 0 будет проверять, соответствует ли x "0.

Оба этих термина определяются спецификацией Javascript.

Ответ 3

Вот интересный вопрос относительно непустой строки, которая имеет только пробельные символы:

!!"   ";         // true
"   " == true;   // false

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

Причина, по которой вы получаете другой результат, состоит в том, что строка с символами пробела преобразуется в число 0 (или falsey), а строка с пробелами, преобразованная только в boolean через !!, рассматривается как непустая строка и, следовательно, true.

Итак:

var x = "   ";

alert( !x );      // false
alert( x == 0 );  // true

EDIT:

Вероятно, важно помнить, что при сравнении числа или булевых значений с типом non number ==, если возможно, использует преобразование toNumber, тогда как ! использует toBoolean-преобразование. Они не всегда одинаковы.

Легко увидеть результат преобразования toBoolean, используя !!. Как в:

alert( !![] );   // true

Но вы не можете увидеть результат преобразования toNumber при использовании ==.

Однако вы можете использовать унарный +, чтобы увидеть результат преобразования toNumber. Как в:

alert( +[] );   // 0

Я уверен, что то, что происходит в случае массива, заключается в том, что он сначала получает вызов toString. Поэтому:

// ---------------------toString result-------toNumber result (from string) 
alert( +[] );       //       ""                   0    
alert( +[""] );     //       ""                   0    
alert( +["    "] ); //       "     "              0    
alert( +[0] );      //       "0"                  0    
alert( +["0"] );    //       "0"                  0    
alert( +["3"] );    //       "3"                  3    
alert( +[3,4] );    //       "3,4"               NaN  

Ответ 4

Короткий ответ: они почти всегда одинаковы, но не на 100% одинаковы.

Примером может быть (!'0'), который является ложным, тогда как ('0' == 0) является истинным

Детали:

От: http://www.joeyjavas.com/2007/08/04/javascript-true-false-checking-for-boolean-values/

Проверка правильности значения true или false в JavaScript. Все значения оцениваются как true, кроме:

0
-0
null
undefined
NaN
empty string
false

Следовательно, (!x) будет истинным для всех вышеперечисленных значений x и только тех.

Что касается (x == 0), это будет верно для любого значения x, которое - при преобразовании в соответствии с правилами преобразования "==" - преобразуется в 0 по сравнению с числом (например, Boolean false value). Другими примерами, сравнивающими true с ==0, являются объекты, которые генерируют 0 из своих методов valueOf() или строку '0', или пустой массив ([])

Ответ 5

Разница между ними заключается в том, что

if ( x ) { ... }

Проверяет, является ли x "правдивым"

В то время как

if ( x == 0 ) { ... }

Производится ли принуждение типа между x и 0.

Я предполагаю, что вы имеете в виду что-то вроде

if (x == 0) vs if (!x)

Основное отличие - это принуждение типа x к числу против проверки, если x является ложным.

Ясно, что NaN сам никогда не будет равен 0, так как его не число. undefined также будет принуждать к NaN, так что не поймается == 0 Я не могу дать хорошее объяснение, почему null не поймано 0, так как Number(null) == 0

Ответ 6

Первый тест будет успешным, если x отличен от нуля или оценивается объектом (в отличие от null или undefined) или является непустой строкой. Поэтому, если x равно 0, условие не работает, но если оно равно "0" , то оно преуспевает.

Второй тест будет успешным, если x конвертируется в 0. Это означает, что он не должен быть null, undefined или объектом для прохождения этого теста. И это может быть "0" или "".

Другими словами, эти условные обозначения не являются противоположностями. Например, значение "0" будет проходить оба теста.

Ответ 7

Фрагмент кода 1 будет выполняться, если x является "ложным" значением. В Javascript это означает 0, -0, null, undefined, NaN, "или false. Code Snippet 2, однако, будет выполняться только в том случае, если x равно нулю. В отличие от первого условия, это не включает другие" ложные" значения.

Ответ 8

После некоторых поисков, измените мой тент. Нет простой логики, неявные операции равенства следует алгоритму. http://interglacial.com/javascript_spec/a-11.html#a-11.9.3

Я не могу лучше подвести итог тому, что описывает алгоритм, он просто станет более запутанным.

Итак, это (!x) эквивалентно (typeof x === false) aka (не верно)
И (x == 0) сравнивается по алгоритму.