Так много ответов делают половину работы. Да, !!X
можно прочитать как «истинность X [представленного как логическое]». Но !!
, с практической точки зрения, не так важно для выяснения того, является ли одна переменная (или даже если многие переменные) правдивой или ложной. !!myVar === true
- это то же самое, что и myVar
. Сравнение !!X
с "реальным" логическим значением бесполезно.
Единственное, что вы получаете с !!
, - это возможность проверять достоверность нескольких переменных относительно друг друга повторяющимся, стандартизованным (и дружественным к JSLint) способом.
Простое преобразование :(
То есть ...
-
0 === false
- это false
.
-
!!0 === false
- это true
.
Вышесказанное не очень полезно. if (!0)
дает те же результаты, что и if (!!0 === false)
. Я не могу придумать хороший случай для преобразования переменной в логическое значение и последующего сравнения с «истинным» логическим значением.
См. "== and! =" Из направлений JSLint (примечание: Крокфорд немного перемещает свой сайт; эта ссылка может умереть в какой-то момент), чтобы немного узнать, почему:
Операторы == и! = Перед сравнением выполняют приведение типов. Это плохо, потому что приводит к истинному значению '\ t \ r \ n' == 0. Это может замаскировать типовые ошибки. JSLint не может надежно определить, правильно ли используется ==, поэтому лучше вообще не использовать == и! = И всегда использовать вместо них более надежные операторы === и! ==.
Если вас беспокоит только то, что значение является правдивым или ложным, используйте краткую форму. Вместо
(foo != 0)
просто скажите
(foo)
и вместо
(foo == 0)
сказать
(!foo)
Обратите внимание, что есть некоторые неинтуитивные случаи, когда логическое значение будет приведено к числу (true
приведено к 1
и false
к 0
) при сравнении логического значения с числом. В этом случае !!
может быть полезен в умственном отношении. Хотя, опять же, , это случаи, когда вы сравниваете не логическое значение с жестко типизированным логическим, что, я думаю, является серьезной ошибкой.
>
╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
║ Original ║ Equivalent ║ Result ║
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
║ if (-1 == true) console.log("spam") ║ if (-1 == 1) ║ undefined ║
║ if (-1 == false) console.log("spam") ║ if (-1 == 0) ║ undefined ║
║ Order doesn't matter... ║ ║ ║
║ if (true == -1) console.log("spam") ║ if (1 == -1) ║ undefined ║
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
║ if (!!-1 == true) console.log("spam") ║ if (true == true) ║ spam ║ better
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
║ if (-1) console.log("spam") ║ if (truthy) ║ spam ║ still best
╚═══════════════════════════════════════╩═══════════════════╩═══════════╝
А в зависимости от вашего двигателя все становится еще безумнее. WScript, например, получает приз.
function test()
{
return (1 === 1);
}
WScript.echo(test());
Из-за некоторого исторического джайва Windows, в окне сообщения будет выведено -1! Попробуйте в командной строке cmd.exe и убедитесь! Но WScript.echo(-1 == test())
по-прежнему дает 0 или false
в WScript. Посмотри в сторону. Это ужасно.
Сравнение правды :)
Но что, если у меня есть два значения, которые мне нужно проверить на равную истинность / ложность?
Представьте, что у нас есть myVar1 = 0;
и myVar2 = undefined;
.
-
myVar1 === myVar2
равно 0 === undefined
и явно неверно.
-
!!myVar1 === !!myVar2
- это !!0 === !!undefined
и верно! Та же правда! (В данном случае оба «имеют правдивость лжи».)
Итак, единственное место, где вам действительно нужно было бы использовать «переменные с логическим преобразованием», было бы в ситуации, когда вы проверяете, имеют ли обе переменные одинаковую правдивость, верно? То есть используйте !!
, если вам нужно увидеть, являются ли две вары оба правдивыми или оба ложными (или нет), то есть равны (или нет) правдивость .
Я не могу придумать отличного, не надуманного варианта использования для этого навскидку. Может быть, у вас есть "связанные" поля в форме?
if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
errorObjects.spouse = "Please either enter a valid name AND age "
+ "for your spouse or leave all spouse fields blank.";
}
Итак, теперь, если у вас есть правдивость для или ложного имени и возраста супруга, вы можете продолжить. В противном случае у вас есть только одно поле со значением (или очень ранний брак), и вам нужно создать дополнительную ошибку в вашей коллекции errorObjects
.
Хотя даже в этом случае !!
действительно лишний. Одного !
было достаточно для преобразования в логическое значение, и вы просто проверяете равенство.
ИЗМЕНИТЬ 24 октября 2017 г., 6 февраля 19 г.:
Сторонние библиотеки, ожидающие явных логических значений
Вот интересный случай ... !!
может быть полезен, когда сторонние библиотеки ожидают явных логических значений.
Реагировать
Например, False в JSX (React) имеет особое значение, которое не срабатывает при простой ложности. Если вы пытались вернуть в JSX что-то вроде следующего, ожидая int в messageCount
...
{messageCount && <div>You have messages!</div>}
... вы можете быть удивлены, увидев, что React отображает 0
, когда у вас нет сообщений. Вы должны явно вернуть false, чтобы JSX не отображался. Приведенный выше оператор возвращает 0
, который JSX с радостью отображает, как и должно. Он не может сказать, что у вас не было Count: {messageCount}
.
-
Одно исправление связано с bangbang, который переводит 0
в !!0
, то есть false
:
{!!messageCount && <div>You have messages!</div>}
-
Документы JSX предлагают вам быть более явным, написать код с комментариями и использовать сравнение для принудительного преобразования в логическое значение.
{messageCount > 0 && <div>You have messages!</div>}
-
Мне удобнее самому справляться с ложью с помощью троичной системы -
{messageCount ? <div>You have messages!</div> : false}
Машинопись
То же самое и в Typescript: если у вас есть функция, которая возвращает логическое значение (или вы присваиваете значение логической переменной), вы [обычно] не можете вернуть / присвоить логическое значение y; это должно быть строго типизированное логическое значение. Это означает, что , если myObject
строго типизирован, , return !myObject;
работает для функции, возвращающей логическое значение, а return myObject;
- нет. Вы должны return !!myObject
(или привести к правильному логическому типу другим способом), чтобы соответствовать ожиданиям Typescript.
Исключение для машинописного текста? Если myObject
был any
, вы вернулись на Дикий Запад JavaScript и можете вернуть его без !!
, даже если ваш возвращаемый тип является логическим.
Имейте в виду, что эти являются соглашениями JSX и Typescript , а не присущими JavaScript .
Но если вы видите странные символы 0
в визуализированном JSX, подумайте о том, что не нужно управлять ложью.
Запомните это как "бах, бах, ты логический"
Для протокола: не делайте того, что там цитируется. Сделайте
if(vertical !== undefined) this.vertical = Boolean(vertical);
- это намного чище и понятнее, что происходит, не требует ненужных назначений, полностью стандартно и так же быстро (в текущих FF и Chrome) jsperf.com/boolean-conversion-speed.«любой порядочный программист должен знать, что происходит ...» - иногда это помогает компилятору сгенерировать лучший код на компилируемых языках. Я знаю, что раньше Microsoft рекомендовала его при использовании кода C, потому что он генерировал лучший код. (Вероятно, это все еще рекомендуется, но я не могу найти ссылку на данный момент).
!! не оператор. Это просто! оператор дважды.
@schabluk, для записи, порядок операций является причиной того, что
!!5/0
производитInfinity
, а неtrue
, как произведеноBoolean(5/0)
.!!5/0
эквивалентен(!!5)/0
- он жеtrue/0
- из-за того, что оператор!
имеет более высокий приоритет, чем оператор/
. Если вы хотите логически преобразовать5/0
с помощью двойного взрыва, вам нужно будет использовать!!(5/0)
.Проще говоря: !! vertical дает логическое значение, определяющее, определено ли 'vertical' или нет.
Что означает !! (x) в C (особенно ядро Linux)?
Для записи, Boolean (5/0) не то же самое, что !! 5/0 - schabluk 12 фев 2015 в 9:45 Да, потому что вы используете второй оператор без скобок. В любом другом случае они такие же логические (5/0), что и !! (5/0)
Просто объясните:
!!value === Boolean(value)
@Gus Просто чтобы вы знали, я прочитал ваш комментарий waaaay еще в 2012 году. В течение 7 лет с тех пор я всегда с юмором говорил в своей голове: «Bang bang! Ты логический!» при инвертировании логического значения, и я всегда помнил, как это произошло в результате. Я решил посмотреть ваш комментарий сегодня и сообщить вам :-)
@ZacharySchuessler thx, я рад, что многим он понравился, и я даже видел, как это цитируется (и цитируется) на обучающих сайтах и тому подобное, теперь это потрясающе :) Никогда не думал, что буду создавать такую популярную мнемонику.
Фил Х. Кстати, в javascript вам не следует проверять переменную с помощью тернарного оператора (! == или ===). Просто используйте (variable == null). Проверка переменной с помощью тернарного оператора означает, что вам нужно будет проверить как undefined, так и null. В javascript (запрос OP) undefined! == null
если this.vertical == "good" и vertical == "other", то this.vertical будет изменено на логическое значение true !! Это не детерминировано. этот код просто изменит тип переменной, что приведет к неожиданным результатам
@Gus Я люблю тебя, кухня, js!