Я видел некоторый код , который , кажется, использовать оператор не признать, в виде двух восклицательных знаков, например , так: !!
. Может кто-нибудь сказать, пожалуйста, что делает этот оператор?
Контекст, в котором я видел это, был,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
javascript
operators
Теория шестиугольника
источник
источник
if(vertical !== undefined) this.vertical = Boolean(vertical);
- это намного чище и яснее, что происходит, не требует ненужного назначения, полностью стандартно и столь же быстро (на текущих FF и Chrome) jsperf.com/boolean-conversion-speed .Boolean(5/0)
это не то же самое, что!!5/0
!!5/0
производит ,Infinity
а неtrue
, как произведеноBoolean(5/0)
.!!5/0
эквивалентно(!!5)/0
- akatrue/0
- из-за того, что!
оператор имеет более высокий приоритет, чем/
оператор. Если вы хотите Booleanize5/0
с использованием двойного взрыва, вам нужно будет использовать!!(5/0)
.Ответы:
Преобразует
Object
вboolean
. Если бы это было falsey (например0
,null
,undefined
и т.д.), то это будетfalse
, в противном случаеtrue
.Так
!!
что не оператор, это просто!
оператор дважды.Пример из реальной жизни "Test IE version":
Если вы ⇒
Но если вы ⇒
источник
Это ужасно неясный способ преобразования типов.
!
это НЕ . Так!true
естьfalse
и!false
естьtrue
.!0
естьtrue
и!1
естьfalse
.Таким образом, вы конвертируете значение в логическое значение, затем инвертируете его, затем снова инвертируете.
источник
userId ? true : false
делает более ясным, что происходит преобразование, и обрабатывает случай, когда значение userId могло быть явно установлено равнымundefined
!!var
вBoolean(var)
... и!!
он быстрее (меньше инструкций для обработки) и короче, чем альтернативы.userId != 0
верноnull
,NaN
иundefined
, но неверно дляfalse
. Если вы хотите именно такое поведение, вы, вероятно, должны быть откровенными об этом. Но даже если он работает точно так же, как!!userId
, неясно, хотите ли вы, чтобы эти значения были здесь ложными, или вы просто не учли правила преобразования типов Javascript.!!expr
возвращает логическое значение (true
илиfalse
) в зависимости от достоверности выражения. Это имеет больше смысла при использовании не-булевых типов. Рассмотрим эти примеры, особенно 3-й пример и далее:источник
!!new Boolean(false) // true
!!Boolean(false) // false
new Boolean(false)
является объектом, и объект является правдивым, даже если он содержит ложное значение!String
,Number
,Date
и т.д.) предназначены для вызываемых как функции тоже, но в этом случае результат отличается!new Boolean(false)
возвращаетobject
времяBoolean(false)
возвращает примитивfalse
. Надеюсь, это имеет смысл.Заварите немного чая:
!!
не оператор. Это двойное использование!
- это логический оператор "не".В теории:
!
определяет «правду» о том, что значение не является:Правда в том, что
false
это не такtrue
(вот почему и!false
приводит кtrue
)Правда в том, что
true
это не такfalse
(вот почему и!true
приводит кfalse
)!!
определяет «правду» о том, что значение не является :Истина заключается в том, что
true
не неtrue
(именно поэтому!!true
результаты вtrue
)Истина заключается в том, что
false
не неfalse
(именно поэтому!!false
результаты вfalse
)Что мы хотим определить в сравнении, так это «правда» о значении ссылки, а не о ценности самой ссылки. Существует вариант использования, в котором мы можем захотеть узнать правду о значении, даже если мы ожидаем, что значение будет
false
(или ложным), или если мы ожидаем, что значение не будет typeofboolean
.На практике:
Рассмотрим краткую функцию, которая определяет функциональные возможности (и в данном случае совместимость с платформой) посредством динамической типизации (так называемая «утиная типизация»). Мы хотим написать функцию, которая возвращает,
true
если браузер пользователя поддерживает<audio>
элемент HTML5 , но мы не хотим, чтобы функция выдавала ошибку, если<audio>
она не определена; и мы не хотим использоватьtry ... catch
для обработки любых возможных ошибок (потому что они грубые); а также мы не хотим использовать проверку внутри функции, которая не будет последовательно раскрывать правду о функции (например,document.createElement('audio')
все равно создаст элемент с именем,<audio>
даже если HTML5<audio>
не поддерживается).Вот три подхода:
Каждая функция принимает аргументы для поиска a
<tag>
и anattribute
, но каждая из них возвращает разные значения в зависимости от того, что определяют сравнения.Но подождите, это еще не все!
Некоторые из вас , наверное , заметили , что в этом конкретном примере, можно было бы просто проверить свойства , используя немного более производительные средства проверки , если рассматриваемый объект имеет свойство. Есть два способа сделать это:
Мы отвлеклись ...
Какими бы редкими ни были эти ситуации, может существовать несколько сценариев, в которых наиболее кратким, наиболее производительным и, следовательно, наиболее предпочтительным способом получения
true
небулева, возможно, неопределенного значения действительно является использование!!
. Надеюсь, это смехотворно проясняет.источник
if()
оператор уже преобразует выражение в логическое значение, явное приведение возвращаемого значения тестирующей функции к логическому является избыточным - поскольку "истинность" === истина в том, что касаетсяif()
оператора в любом случае. Или я пропускаю сценарий, в котором вам НУЖНО правдивое выражение, чтобы на самом деле быть логическимtrue
?if()
действительно приводят логические значения против значений Falsey, но говорят, что вы действительно хотите установить логический флаг для объекта - он не будет приводить его, какif()
оператор. Напримерobject.hasTheThing = !!castTheReturnValToBoolNoMatterWhat()
, установил быtrue
илиfalse
вместо реального возвращаемого значения. Другим примером является , возможно , все админыid
из0
и не-админы идентификатор1
или выше. Чтобы получить,true
если кто-то не является администратором, вы могли бы сделатьperson.isNotAdmin = !!admin.id
. Мало случаев использования, но это сжато, когда есть.!!
преобразует значение справа от него в эквивалентное логическое значение. (Подумайте о том, как бедняк «набирает текст»). Его цель обычно состоит в том, чтобы донести до читателя, что коду не важно, какое значение находится в переменной, а какое значение является «истинным» .источник
!
прежнему переворачивает значение вправо. В случае логического значения самое правое!
отрицает значение, а самое левое!
отрицает его еще раз. Чистый эффект состоит в том, что изменений нет, но большинство движков генерируют коды операций для двойного отрицания.if(0){...
Javascript уже знает, что это неверно. Почему лучше сказатьif(!!0){...
?!!foo
применяет унарный оператор not дважды и используется для приведения к логическому типу, аналогично использованию унарного плюса+foo
для приведения к числу и конкатенации пустой строки''+foo
для приведения к строке.Вместо этих хаков вы также можете использовать функции конструктора, соответствующие типам примитивов ( без использования
new
), для явного приведения значений, т.е.источник
new
- как явно указано в моем ответеx="0"
просто сделайте следующее:x=!!+x; //false
то же самое, что иBoolean(Number(x))
число (или + x), преобразует строку «0» в 0, которое оценивается как ложное, а затем логическое значение (!! x) бросает его в логическое значение напрямую. Очень просто!!!+x
противx !== "0"
?Так много ответов делают половину работы. Да,
!!X
может быть прочитано как «истинность X [представлена как логическое значение]». Но!!
, на самом деле, это не так важно для выяснения, является ли единственная переменная (или даже если много переменных) истинной или ложной.!!myVar === true
так же, как простоmyVar
. Сравнение!!X
с «настоящим» логическим значением не очень полезно.То, что вы приобретаете,
!!
это возможность проверять достоверность нескольких переменных друг против друга повторяемым, стандартизированным (и дружественным JSLint) способом.Просто кастинг :(
Это...
0 === false
естьfalse
.!!0 === false
естьtrue
.Выше не очень полезно.
if (!0)
дает те же результаты, что иif (!!0 === false)
. Я не могу придумать хорошего случая для приведения переменной к логическому, а затем сравнения с «истинным» логическим значением.См. "== и! =" Из указаний JSLint (примечание: Крокфорд немного перемещает свой сайт; в какой-то момент эта ссылка может умереть), чтобы узнать, почему:
Обратите внимание, что есть некоторые неинтуитивные случаи, когда логическое значение будет приведено к числу (
true
приведено к1
иfalse
к0
) при сравнении логического значения с числом. В этом случае!!
может быть психически полезным. Хотя, опять же, это те случаи, когда вы сравниваете не-булево значение со строго типизированным логическим значением, что, на мой взгляд, является серьезной ошибкой.if (-1)
путь до сих порИ все становится еще безумнее в зависимости от вашего двигателя. WScript, например, выигрывает приз.
Из-за некоторого исторического джайва Windows это выведет -1 в окне сообщения! Попробуйте в командной строке cmd.exe и посмотрите! Но
WScript.echo(-1 == test())
все равно выдает 0 или WScriptfalse
. Отвернись. Это отвратительноСравнивая правдивость :)
Но что, если у меня есть два значения, которые мне нужно проверить на одинаковую истинность / ложность?
Притворись , мы имеем
myVar1 = 0;
иmyVar2 = undefined;
.myVar1 === myVar2
есть0 === undefined
и, очевидно, ложно.!!myVar1 === !!myVar2
это!!0 === !!undefined
и есть правда! Та же самая правдивость! (В этом случае оба «имеют ложную правду».)Таким образом, единственное место, где вам действительно нужно использовать «переменные логического преобразования», было бы, если бы у вас была ситуация, когда вы проверяете, имеют ли обе переменные одинаковую истинность, верно? То есть используйте,
!!
если вам нужно увидеть, являются ли две переменные правдивыми или ложными (или нет), то есть равными (или нет) правдивостью .Я не могу придумать отличный, не надуманный сценарий использования для этого случая. Может быть, у вас есть «связанные» поля в форме?
Так что теперь, если у вас есть правдивое для обоих или ложное имя и возраст супруга, вы можете продолжить. В противном случае у вас есть только одно поле со значением (или очень ранний брак), и вам нужно создать дополнительную ошибку в вашей
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 && <div>Get your count to zero!</div>}
(или что-то менее надуманное).Одним из способов исправить включает 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.Имейте в виду, что это соглашения JSX и Typescript , а не присущие JavaScript .
Но если вы видите странные
0
s в вашем рендеринге JSX, подумайте о ложном управлении.источник
if (!!window.Worker)
true
« внешность » действуют точно так же вif
. Я продолжаю пытаться, но не могу придумать причину, по которой приведение истинности к булевому значению предпочтительнее за пределами вышеупомянутого сложного случая «сравнить правдивость», за исключением читабельности, если вы повторно используете значение позже, как вq
примере с библиотекой. , Но даже тогда это ярлык с потерями информации, и я бы сказал, что каждый раз вам лучше оценивать правдивость.Это просто логический оператор NOT, дважды - он используется для преобразования чего-либо в логическое значение, например:
источник
Он преобразует суффикс в логическое значение.
источник
Это двойная
not
операция. Первый!
преобразует значение в логическое значение и инвертирует его логическое значение. Вторая!
инвертирует логическое значение обратно.источник
Похоже, что
!!
оператор приводит к двойному отрицанию.источник
Имитирует поведение
Boolean()
функции приведения. ПервоеNOT
возвращает логическое значение независимо от того, какой операнд ему дан. ВтороеNOT
отрицает этоBoolean
значение и, таким образом, даетtrue
логическое значение переменной. Конечный результат такой же, как использованиеBoolean()
функции для значения.источник
! is "boolean not", который по существу типизирует значение "enable" к его логическому противоположному значению. Второй ! переворачивает это значение. Таким образом,
!!enable
означает «не активировать», давая вам значениеenable
как логическое значение.источник
Я думаю, стоит упомянуть, что условие в сочетании с логическим И / ИЛИ не будет возвращать логическое значение, но последний успех или первый сбой в случае && и первый успех или последний сбой в случае || цепи условий.
Чтобы привести условие к истинному логическому литералу, мы можем использовать двойное отрицание:
источник
!!
он используетNOT
операцию дважды вместе,!
преобразует значение в aboolean
и переворачивает его, вот простой пример, чтобы увидеть, как!!
работает:Во-первых, место у вас есть:
Затем вы это сделаете
!0
, он будет преобразован в логическое значение и будет оцененtrue
как 0falsy
, так что вы получите обратное значение и конвертированы в логическое значение, так что оно будет оценено какtrue
.но нам не нужна обратная логическая версия значения, поэтому мы можем отменить ее снова, чтобы получить наш результат! Вот почему мы используем другое
!
.По сути,
!!
убедитесь, что мы получаем логическое значение, а не ложное, правдивое или строковое и т. Д.Так что это похоже на использование
Boolean
функции в javascript, но простой и короткий способ преобразования значения в логическое значение:источник
!!
Конструкция представляет собой простой способ превратить любое выражение JavaScript в его булевой эквивалент.Например:
!!"he shot me down" === true
и!!0 === false
.источник
0 === false
это ложь и!!0 === false
правда.Это не один оператор, это два. Это эквивалентно следующему и является быстрым способом приведения значения к логическому значению.
источник
Я подозреваю, что это остаток от C ++, где люди переопределяют! оператор, но не оператор bool.
Таким образом, чтобы получить отрицательный (или положительный) ответ в этом случае, вам сначала нужно использовать! оператор, чтобы получить логическое значение, но если вы хотите проверить положительный случай, используйте !!.
источник
Операторы
if
andwhile
и?
оператор используют значения истинности, чтобы определить, какую ветвь кода следует запустить. Например, нулевые и NaN числа и пустая строка являются ложными, но другие числа и строки являются истинными. Объекты имеют значение true, но неопределенное значение иnull
оба являются false.Оператор двойного отрицания
!!
вычисляет истинное значение значения. Это на самом деле два оператора, где!!x
означает!(!x)
, и ведет себя следующим образом:x
это ложное значение,!x
естьtrue
и!!x
естьfalse
.x
это истинное значение,!x
этоfalse
и!!x
естьtrue
.При использовании на верхнем уровне булева контекста (
if
,while
или?
), то!!
оператор не поведенческий не-оп. Например,if (x)
иif (!!x)
значат одно то же.Практическое использование
Однако он имеет несколько практических применений.
Одним из способов является сжатие с потерями объекта до его истинного значения, чтобы ваш код не содержал ссылку на большой объект и не поддерживал его. Присвоение
!!some_big_object
переменной вместоsome_big_object
отпускания ее для сборщика мусора. Это полезно в случаях, когда создается либо объект, либо ложное значение, например,null
или неопределенное значение, например обнаружение функций браузера.Другое использование, о котором я упоминал в ответе о соответствующем
!!
операторе C , - это инструменты «lint», которые ищут общие опечатки и диагностику печати. Например, как в C, так и в JavaScript несколько общих опечаток для логических операций приводят к другому поведению, вывод которого не совсем как логический:if (a = b)
является ли присвоение с последующим использованием значения истинностиb
;if (a == b)
это сравнение равенства.if (a & b)
является побитовым И;if (a && b)
это логическое И.2 & 5
есть0
(ложное значение);2 && 5
правда.!!
Оператор успокаивает инструмент ворса, что вы написали , что вы имели в виду: сделать эту операцию, возьмите значение истинности результата.Третье использование - создание логического XOR и логического XNOR. И в C, и в JavaScript
a && b
выполняет логическое И (истинно, если обе стороны верны) иa & b
выполняет побитовое И.a || b
выполняет логическое ИЛИ (истина, если хотя бы одно из них истинно) иa | b
выполняет побитовое ИЛИ. Существует побитовое XOR (исключающее ИЛИ) какa ^ b
, но нет встроенного оператора для логического XOR (истина, если истинна только одна сторона). Например, вы можете разрешить пользователю вводить текст точно в одно из двух полей. Что вы можете сделать , это преобразовать каждый в значение истинности и сравнить их:!!x !== !!y
.источник
Двойное логическое отрицание. Часто используется для проверки, если значение не определено.
источник
Тонны хороших ответов здесь, но если вы прочитали это далеко, это помогло мне «получить это». Откройте консоль в Chrome (и т. Д.) И начните вводить:
Естественно, это все равно, что просто набирать !! someThing, но добавленные скобки могут помочь сделать его более понятным.
источник
!!x
это сокращение дляBoolean(x)
Первый удар заставляет двигатель js работать,
Boolean(x)
но также имеет побочный эффект инвертирования значения. Таким образом, второй удар отменяет побочный эффект.источник
Это заставляет все вещи к булеву.
Например:
источник
На этот вопрос был дан довольно подробный ответ, но я хотел бы добавить ответ, который, я надеюсь, будет максимально упрощенным, что придает смысл !! так просто понять, как это может быть.
Поскольку javascript имеет значения, которые называются «истинными» и «ложными» значениями, существуют выражения, которые при оценке в других выражениях приведут к условию «истина» или «ложь», даже если проверяемое значение или выражение на самом деле не является
true
илиfalse
.Например:
Если этот элемент действительно существует, выражение будет оцениваться как true, и будет выполнен блок кода.
Однако:
... НЕ приведет к истинному условию, и блок кода не будет выполнен, даже если элемент существует.
Почему? Потому
document.getElementById()
что это «истинное» выражение, которое будет оцениваться как истинное в этомif()
утверждении, но это не фактическое логическое значениеtrue
.Двойное «не» в этом случае довольно просто. Это просто два
not
спина к спине.Первый просто «инвертирует» истинное или ложное значение, в результате чего получается фактический логический тип, а затем второй «инвертирует» его обратно в исходное состояние, но теперь в фактическое логическое значение. Таким образом, у вас есть последовательность:
а также
ОБА вернет истину, как и ожидалось.
источник
Я просто хотел добавить, что
такой же как
Но это может быть проблемой, когда что-то не определено.
Хитрость здесь в том, что цепочка
&&
s вернет первое найденное значение Falsey - и это может быть передано в оператор if и т. Д. Поэтому, если b.foo не определен, он вернет undefined и пропуститb.foo.bar
оператор, и мы не получим ошибка.Вышеприведенный возврат не определен, но если у вас есть пустая строка, false, null, 0, undefined, эти значения будут возвращены, и как только мы встретим их в цепочке, -
[]
и{}
они оба будут «истинными», и мы продолжим в так называемом » && цепочка "к следующему значению справа.PS Еще один способ сделать то же самое
(b || {}).foo
, потому что, если b не определено, тоb || {}
будет{}
, и вы будете получать доступ к значению в пустом объекте (без ошибок) вместо того, чтобы пытаться получить доступ к значению в пределах «неопределенного» (вызывает ошибку ). Итак, так(b || {}).foo
же, какb && b.foo
и так((b || {}).foo || {}).bar
же, какb && b.foo && b.foo.bar
.источник
({}).anything
, дастundefined
Увидев все эти замечательные ответы, я хотел бы добавить еще одну причину использования
!!
. В настоящее время я работаю в Angular 2-4 (TypeScript) и хочу вернуть логическое значение, какfalse
если бы мой пользователь не проходил аутентификацию. Если он не аутентифицирован, токен-строка будетnull
или""
. Я могу сделать это с помощью следующего блока кода:источник
вот кусок кода от угловой JS
их намерение состоит в том, чтобы установить для rafSupported значение true или false в зависимости от наличия функции в requestAnimationFrame
это может быть достигнуто путем проверки в целом следующим образом:
короткий путь мог бы использовать!
так что если requestAnimationFrame была назначена функция, то! requestAnimationFrame будет false и еще один! это было бы правдой
если бы requestAnimationFrame был определен как неопределенный, тогда! requestAnimationFrame был бы верным и еще одним! это было бы ложным
источник
Некоторые операторы в JavaScript выполняют неявные преобразования типов, а иногда используются для преобразования типов.
Унарный
!
оператор преобразует свой операнд в логическое значение и отрицает его.Этот факт приводит к следующей идиоме, которую вы можете увидеть в своем исходном коде:
источник
Используйте логический оператор not два раза,
это значит! True = false
и !! true = true
источник
Возвращает логическое значение переменной.
Вместо этого
Boolean
можно использовать класс.(пожалуйста, прочтите описание кода)
А именно
Boolean(X) = !!X
в использовании.Пожалуйста, проверьте фрагмент кода ниже ↓
источник