Что !! (не нет) оператор в JavaScript?

Я видел некоторый код , который , кажется, использовать оператор не признать, в виде двух восклицательных знаков, например , так: !!. Может кто-нибудь сказать, пожалуйста, что делает этот оператор?

Контекст, в котором я видел это, был,

this.vertical = vertical !== undefined ? !!vertical : this.vertical;
24.04.2009 08:13:58
Помните это как "взрыв, взрыв, вы булевы"
Gus 15.02.2012 18:35:02
Просто для записи, не делайте того, что там указано. Делайте if(vertical !== undefined) this.vertical = Boolean(vertical);- это намного чище и яснее, что происходит, не требует ненужного назначения, полностью стандартно и столь же быстро (на текущих FF и Chrome) jsperf.com/boolean-conversion-speed .
Phil H 12.02.2014 09:43:45
!! не оператор. Это просто! оператор дважды.
Vivek 16.07.2014 07:21:21
Просто для записи, Boolean(5/0)это не то же самое, что!!5/0
schabluk 12.02.2015 09:45:25
@schabluk, для записи, порядок операций является причиной !!5/0производит , Infinityа не true, как произведено Boolean(5/0). !!5/0эквивалентно (!!5)/0- aka true/0- из-за того, что !оператор имеет более высокий приоритет, чем /оператор. Если вы хотите выполнить Booleanize 5/0с помощью двойного взрыва, вам нужно использовать !!(5/0).
matty 24.05.2015 13:47:42
30 ОТВЕТОВ
РЕШЕНИЕ

Преобразует Objectв boolean. Если бы это было falsey (например 0, null, undefinedи т.д.), то это будет false, в противном случае true.

!oObject  // inverted boolean
!!oObject // non inverted boolean so true boolean representation

Так !!что не оператор, это просто !оператор дважды.

Пример из реальной жизни "Test IE version":

const isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);  
console.log(isIE8); // returns true or false 

Если вы ⇒

console.log(navigator.userAgent.match(/MSIE 8.0/));  
// returns either an Array or null  

Но если вы ⇒

console.log(!!navigator.userAgent.match(/MSIE 8.0/));  
// returns either true or false
2711
7.02.2020 11:40:54
Он преобразует небулево значение в инвертированное логическое значение (например,! 5 будет ложным, поскольку 5 - не ложное значение в JS), а затем логическое инвертирует, так что вы получите исходное значение как логическое значение (так что !! 5 будет будь настоящим).
Chuck 24.04.2009 17:14:18
Простой способ описать это: Boolean (5) === !! 5; Тот же кастинг, меньше персонажей.
Micah Snyder 24.04.2009 18:27:27
Это используется для преобразования истинных значений в булево значение true, а ложные значения слишком булево значение false.
thetoolman 16.07.2012 03:53:22
@Micah Snyder, будьте осторожны, в JavaScript лучше использовать логические примитивы, а не создавать объекты, которые упаковывают логические значения с помощью нового Boolean (). Вот пример, чтобы увидеть разницу: jsfiddle.net/eekbu
victorvartan 3.02.2013 12:24:32
Насколько я знаю, этот шаблон bang-bang бесполезен в операторе if (… _; только в операторе return функции, которая должна возвращать логическое значение.
rds 26.03.2014 19:43:13

Это просто логический оператор NOT, дважды - он используется для преобразования чего-либо в логическое значение, например:

true === !!10

false === !!0
54
24.04.2009 08:18:49
С какой стати ты это сделал? Использовать ! оператор для преобразования в логическое значение, а затем использовать === для сравнения типа? Просто примите, что у вас нет безопасности типов и делайте val> 0 или что-то еще.
Darren Clark 24.04.2009 08:41:48
@Darren: он не сравнивает типы; он говорит вам, каковы результаты, записывая утверждения в своем ответе.
Lightness Races in Orbit 9.11.2011 10:34:34

Похоже, что !!оператор приводит к двойному отрицанию.

var foo = "Hello World!";

!foo // Result: false
!!foo // Result: true
23
9.11.2011 10:35:33

Я подозреваю, что это остаток от C ++, где люди переопределяют! оператор, но не оператор bool.

Таким образом, чтобы получить отрицательный (или положительный) ответ в этом случае, вам сначала нужно использовать! оператор, чтобы получить логическое значение, но если вы хотите проверить положительный случай, используйте !!.

10
24.04.2009 08:33:39

!!преобразует значение справа от него в эквивалентное логическое значение. (Подумайте о том, как бедняк «набирает текст»). Его цель обычно состоит в том, чтобы донести до читателя, что коду не важно, какое значение находится в переменной, а какое значение «истинно» .

101
10.09.2009 17:26:53
Или в случае логического значения справа, это ничего не делает.
Daniel A. White 10.09.2009 17:28:56
@Daniel: по- !прежнему переворачивает значение вправо. В случае логического значения самое правое !отрицает значение, а самое левое !отрицает его еще раз. Чистый эффект заключается в том, что изменений нет, но большинство движков генерируют коды операций для двойного отрицания.
Crescent Fresh 10.09.2009 17:34:00
Но какой в ​​этом смысл? Если я это сделаю, if(0){...Javascript уже знает, что это неверно. Почему лучше сказать if(!!0){...?
CodyBugstein 6.05.2016 23:37:00
дело в переменных, которые вы, возможно, не знаете, их содержание; если это может быть целое число или строка, объект или ноль, неопределенный и т. д. Это простой способ проверить существование.
mix3d 22.09.2016 12:59:18

Он преобразует суффикс в логическое значение.

32
29.10.2009 21:22:40

Это ужасно неясный способ преобразования типов.

!это НЕ . Так !trueесть falseи !falseесть true. !0есть trueи !1есть false.

Таким образом, вы конвертируете значение в логическое значение, затем инвертируете его, затем снова инвертируете.

// Maximum Obscurity:
val.enabled = !!userId;

// Partial Obscurity:
val.enabled = (userId != 0) ? true : false;

// And finally, much easier to understand:
val.enabled = (userId != 0);
846
26.09.2011 14:08:52
!! ложь = ложь. !! true = true
cllpse 10.09.2009 17:38:29
Неужели вариант «намного легче понять» действительно легче понять? Проверка на 0 не является реальной проверкой на 0, но проверка на несколько странный список значений, который Javascript считает равным 0. Это userId ? true : false делает более ясным, что происходит преобразование, и обрабатывает случай, когда значение userId могло быть явно установлено равнымundefined
Ben Regenspan 13.10.2010 16:26:22
У моего мозга нет проблем с расшифровкой !!varв Boolean(var)... и !!он быстрее (меньше инструкций для обработки) и короче, чем альтернативы.
adamJLev 24.10.2010 23:36:07
@RickyClarkson в основном для удобства чтения, поскольку синтаксически это не требуется. Некоторые используют соглашение всегда заключать условные скобки в круглые скобки, чтобы отделить его от остальной части выражения.
Dave Rager 18.05.2012 19:29:12
Я не согласен с этим. userId != 0верно null, NaNи undefined, но неверно для false. Если вы хотите именно такое поведение, вы, вероятно, должны быть откровенными об этом. Но даже если он работает точно так же, как !!userId, неясно, хотите ли вы, чтобы эти значения были здесь ложными, или вы просто не учли правила преобразования типов в Javascript.
philh 30.09.2014 08:50:49

Это двойная notоперация. Первый !преобразует значение в логическое значение и инвертирует его логическое значение. Вторая !инвертирует логическое значение обратно.

26
10.09.2009 17:28:46

! is "boolean not", который по существу типизирует значение "enable" к его логическому противоположному значению. Второй ! переворачивает это значение. Таким образом, !!enableозначает «не активировать», давая вам значение enableкак логическое значение.

20
10.09.2009 17:29:18

!!fooприменяет унарный оператор not дважды и используется для приведения к логическому типу, аналогично использованию унарного плюса +fooдля приведения к числу и конкатенации пустой строки ''+fooдля приведения к строке.

Вместо этих хаков вы также можете использовать функции конструктора, соответствующие типам примитивов ( без использования new), для явного приведения значений, т.е.

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo
70
10.09.2009 21:15:16
Но тогда вы можете столкнуться с проблемами с instanceof. new Boolean (1) instanceof Object -> true !! 1 instanceof Object -> false
Seamus 7.10.2010 12:53:30
нет, вы не можете: заметьте, что функции конструктора вызываются без new- как явно указано в моем ответе
Christoph 8.10.2010 09:46:04
фантастический! Это полезно для небольшого взлома, когда вам нужно оценивать строки с «0» как false вместо true. (т.е. при чтении значений из select, потому что они читаются как String). Таким образом, если вы хотите считать «0» отрицательным (логическое значение «ложь»), то x="0"просто сделайте следующее: x=!!+x; //falseто же самое, что и Boolean(Number(x))число (или + x), преобразует строку «0» в 0, которая оценивается как ложное, а затем логическое значение (!! x) бросает его в логическое значение напрямую. Очень просто!
DiegoDD 3.06.2013 18:13:58
@DiegoDD почему бы вы выбрали !!+xпротив x !== "0"?
placeybordeaux 29.12.2015 23:46:02
@placeybordeaux, потому что, например, вы можете преобразовать значение и присвоить его другой переменной, независимо от того, собираетесь ли вы сравнить его с чем-то другим или нет.
DiegoDD 5.01.2016 18:26:40

Это не один оператор, это два. Это эквивалентно следующему и является быстрым способом приведения значения к логическому значению.

val.enabled = !(!enable);
14
10.09.2009 21:19:09

Двойное логическое отрицание. Часто используется для проверки, если значение не определено.

8
2.12.2010 20:21:14

Имитирует поведение Boolean()функции приведения. Первое NOTвозвращает логическое значение независимо от того, какой операнд ему дан. Второе NOTотрицает это Booleanзначение и, таким образом, дает trueлогическое значение переменной. Конечный результат такой же, как использование Boolean()функции для значения.

23
23.03.2011 11:53:45

Это действительно удобный способ проверить наличие неопределенных, «неопределенных», нулевых, «нулевых», «»

if (!!var1 && !!var2 && !!var3 && !!var4 ){
   //... some code here
}
-3
24.04.2012 12:22:05
Почему? Мне все еще нужно знать, что в var1 через 4 есть значения.
rob_james 28.10.2012 17:22:37
Потому что &&операторы уже «конвертируют» свои операторы в логические.
nalply 29.10.2012 07:31:33
да - круто! Приветствия. Для записи, я пытался указать, что было бы хорошо проверить много значений. Вы можете представить, что делаете это без логического преобразования ?! Психические! Во всяком случае, это полезно знать. То же самое происходит с ||?
rob_james 29.10.2012 21:25:10
Я должен забрать свой комментарий. Я был неправ. Это не &&операторы, а ifутверждение, которое «конвертирует». Возможно, хороший вопрос StackOverflow?
nalply 30.10.2012 09:16:04
Я думаю, что это оператор &&, как будто вы удаляете окружающее
aikeru 21.08.2013 21:18:59

!!exprвозвращает логическое значение ( trueили false) в зависимости от достоверности выражения. Это имеет больше смысла при использовании не-булевых типов. Рассмотрим эти примеры, особенно 3-й пример и далее:

          !!false === false
           !!true === true

              !!0 === false
!!parseInt("foo") === false // NaN is falsy
              !!1 === true
             !!-1 === true  // -1 is truthy

             !!"" === false // empty string is falsy
          !!"foo" === true  // non-empty string is truthy
        !!"false" === true  // ...even if it contains a falsy value

     !!window.foo === false // undefined is falsy
           !!null === false // null is falsy

             !!{} === true  // an (empty) object is truthy
             !![] === true  // an (empty) array is truthy; PHP programmers beware!
443
24.10.2015 21:00:47
Стоит отметить:!!new Boolean(false) // true
Camilo Martin 18.12.2012 08:05:51
... Но также!!Boolean(false) // false
Camilo Martin 18.12.2012 08:06:37
new Boolean(false)является объектом, и объект является правдивым, даже если он содержит ложное значение!
Salman A 18.12.2012 08:15:21
Да , я знаю, но учитывать тот факт , что большинство родных Конструкторов ( String, Number, Dateи т.д.) предназначены для вызываемых как функции тоже, но в этом случае результат отличается!
Camilo Martin 18.12.2012 08:25:00
@CamiloMartin: только что понял, что new Boolean(false)возвращает objectвремя Boolean(false)возвращает примитив false . Надеюсь, это имеет смысл.
Salman A 26.02.2013 11:02:44

Заварите немного чая:

!!не оператор. Это двойное использование !- это логический оператор «не».


В теории:

! определяет «правду» о том, что значение не является:

  • Правда в том, что falseэто не так true(поэтому !falseприводит к true)

  • Правда в том, что trueэто не так false(поэтому !trueприводит к false)


!!определяет «правду» о том, что значение не является :

  • Истина заключается в том, что trueне не true (именно поэтому !!trueрезультаты в true)

  • Истина заключается в том, что falseне не false (именно поэтому !!falseрезультаты в false)


Что мы хотим определить при сравнении, так это «правда» о значении ссылки, а не о ценности самой ссылки. Существует вариант использования, в котором мы можем захотеть узнать правду о значении, даже если мы ожидаем, что значение будет false(или ложным), или если мы ожидаем, что значение не будет typeof boolean.


На практике:

Рассмотрим краткую функцию, которая определяет функциональные возможности (и в данном случае совместимость с платформой) посредством динамической типизации (так называемая «утиная типизация»). Мы хотим написать функцию, которая возвращает, trueесли браузер пользователя поддерживает <audio>элемент HTML5 , но мы не хотим, чтобы функция выдавала ошибку, если <audio>она не определена; и мы не хотим использовать try ... catchдля обработки любых возможных ошибок (потому что они грубые); а также мы не хотим использовать проверку внутри функции, которая не будет последовательно раскрывать правду о функции (например, document.createElement('audio')все равно создаст элемент с именем, <audio>даже если HTML5 <audio>не поддерживается).


Вот три подхода:

// this won't tell us anything about HTML5 `<audio>` as a feature
var foo = function(tag, atr) { return document.createElement(tag)[atr]; }

// this won't return true if the feature is detected (although it works just fine)
var bar = function(tag, atr) { return !document.createElement(tag)[atr]; }

// this is the concise, feature-detecting solution we want
var baz = function(tag, atr) { return !!document.createElement(tag)[atr]; }

foo('audio', 'preload'); // returns "auto"
bar('audio', 'preload'); // returns false
baz('audio', 'preload'); // returns true

Каждая функция принимает аргументы для поиска a <tag>и an attribute, но каждая из них возвращает разные значения в зависимости от того, что определяют сравнения.

Но подождите, это еще не все!

Некоторые из вас , наверное , заметили , что в этом конкретном примере, можно было бы просто проверить свойства , используя немного более производительные средства проверки , если рассматриваемый объект имеет свойство. Есть два способа сделать это:

// the native `hasOwnProperty` method
var qux = function(tag, atr) { return document.createElement(tag).hasOwnProperty(atr); }

// the `in` operator
var quux = function(tag, atr) { return atr in document.createElement(tag); }

qux('audio', 'preload');  // returns true
quux('audio', 'preload'); // returns true

Мы отвлеклись ...

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

153
22.02.2013 23:45:27
совершенно потрясающий ответ, но я не вижу полезности !! построить. Поскольку if()оператор уже преобразует выражение в логическое значение, явное приведение возвращаемого значения тестирующей функции к логическому является избыточным - поскольку "истинность" === истина в том, что касается if()оператора в любом случае. Или я пропускаю сценарий, в котором вам НУЖНО правдивое выражение, чтобы на самом деле быть логическим true?
Tom Auger 6.04.2016 13:27:19
Операторы @TomAuger приводят if()логические значения против значений Falsey, но говорят, что вы действительно хотите установить логический флаг на объекте - он не будет приводить его, как это if()делает оператор. Например object.hasTheThing = !!castTheReturnValToBoolNoMatterWhat(), установил бы trueили falseвместо реального возвращаемого значения. Другим примером является , возможно , все админы idиз 0и не-админы идентификатор 1или выше. Чтобы получить, trueесли кто-то не является администратором, вы могли бы сделать person.isNotAdmin = !!admin.id. Мало случаев использования, но это сжато, когда есть.
Benny 31.05.2018 15:41:36

!!Конструкция представляет собой простой способ превратить любое выражение JavaScript в его булевой эквивалент.

Например: !!"he shot me down" === trueи !!0 === false.

15
10.09.2015 08:20:11
Очень близко к важному различию. Ключ в том, что 0 === falseэто ложь и !!0 === falseправда.
ruffin 29.04.2015 17:38:22

Тонны хороших ответов здесь, но если вы прочитали это далеко, это помогло мне «получить это». Откройте консоль в Chrome (и т. Д.) И начните вводить:

!(!(1))
!(!(0))
!(!('truthy')) 
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)

Естественно, это все равно, что просто набирать !! someThing, но добавленные скобки могут помочь сделать его более понятным.

8
24.04.2014 13:05:49
a = 1;
alert(!a) // -> false : a is not not defined
alert(!!a) // -> true : a is not not defined

Для !a, он проверяет , является ли aэто НЕ определено, в то время как !!aпроверяет , является ли переменная определена.

!!aтак же, как !(!a). Если aопределено, aесть true, !aесть falseи !!aесть true.

2
28.06.2014 03:35:13

вот кусок кода от угловой JS

var requestAnimationFrame = $window.requestAnimationFrame ||
                                $window.webkitRequestAnimationFrame ||
                                $window.mozRequestAnimationFrame;

 var rafSupported = !!requestAnimationFrame;

их намерение состоит в том, чтобы установить для rafSupported значение true или false в зависимости от наличия функции в requestAnimationFrame

это может быть достигнуто путем проверки в целом следующим образом:

if(typeof  requestAnimationFrame === 'function')
rafSupported =true;
else
rafSupported =false;

короткий путь мог бы использовать!

rafSupported = !!requestAnimationFrame ;

так что если requestAnimationFrame была назначена функция, то! requestAnimationFrame будет ложным и еще одним! это было бы правдой

если бы requestAnimationFrame был определен как неопределенный, тогда! requestAnimationFrame был бы верным и еще одним! это было бы ложным

4
4.03.2015 08:25:35

Так много ответов делают половину работы. Да, !!Xможет быть прочитано как «истинность X [представлена ​​как логическое значение]». Но !!, на самом деле, это не так важно для выяснения, является ли единственная переменная (или даже если много переменных) истинной или ложной. !!myVar === trueтак же, как просто myVar. Сравнение !!Xс «настоящим» логическим значением не очень полезно.

То, что вы приобретаете, !!это возможность проверять достоверность нескольких переменных друг против друга повторяемым, стандартизированным (и дружественным JSLint) способом.

Просто кастинг :(

Это...

  • 0 === falseесть false.
  • !!0 === falseесть true.

Выше не так полезно. if (!0)дает те же результаты, что и if (!!0 === false). Я не могу придумать хорошего случая для приведения переменной к логическому, а затем сравнения с «истинным» логическим значением.

Посмотрите "== и! =" Из указаний JSLint (примечание: Крокфорд немного перемещает свой сайт; в какой-то момент эта ссылка может умереть), чтобы узнать, почему:

Операторы == и! = Выполняют приведение типов перед сравнением. Это плохо, потому что это заставляет '\ t \ r \ n' == 0 быть верным. Это может маскировать ошибки типа. JSLint не может надежно определить, правильно ли используется ==, поэтому лучше вообще не использовать == и! = И всегда использовать вместо этого более надежные операторы === и! ==.

Если вас волнует только то, что значение является правдивым или ложным, используйте короткую форму. Вместо
(foo != 0)

просто скажи
(foo)

и вместо
(foo == 0)

сказать
(!foo)

Обратите внимание , что есть некоторые неинтуитивные случаи , когда логическое значение будет отлитые в ряд ( trueналивает 1и falseв 0) при сравнении булева к ряду. В этом случае !!может быть психически полезным. Хотя, опять же, это те случаи, когда вы сравниваете не-логическое значение с жестко типизированным логическим значением, что, на мой взгляд, является серьезной ошибкой. if (-1)путь до сих пор

╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
               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 или WScript false. Отвернись. Это отвратительно

Сравнивая правдивость :)

Но что, если у меня есть два значения, которые мне нужно проверить на одинаковую истинность / ложность?

Притворись , мы имеем 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 && <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.

Исключение для Typescript? Если myObjectбыл any, вы вернулись в JavaScript Дикого Запада и может вернуть его без !!, даже если ваш тип возвращаемого значения является логическим.

Имейте в виду, что это соглашения JSX и Typescript , а не присущие JavaScript .

Но если вы видите странные 0s в вашем рендеринге JSX, подумайте о ложном управлении.

66
6.02.2019 13:55:20
Хорошее объяснение. Так бы ты сказал !! не является строго необходимым в этом примере обнаружения функции Worker ? if (!!window.Worker)
jk7 6.05.2015 20:41:37
Нет, тебе это не понадобится. Истина и true« внешность » действуют точно так же в if. Я продолжаю пытаться, но не могу придумать причину, по которой приведение истинности к булевому значению предпочтительнее за пределами вышеупомянутого сложного случая сравнения правдивости, за исключением читабельности, если вы повторно используете значение позже, как в qпримере с библиотекой. , Но даже тогда это ярлык с потерей информации, и я бы сказал, что каждый раз вам лучше оценивать правдивость.
ruffin 6.05.2015 20:54:57
Реакция является основной причиной, по которой мы начали использовать !! шаблон, но это бывает очень удобная и повторяемая вещь. Мне нужно беспокоиться только об истинности или ложности чего-либо, а не о том, что является основным типом.
user1630889 28.07.2018 23:02:49
Прогнозы без комментариев затрудняют решение вашей проблемы! Дайте мне знать, что выглядит плохо, и я буду рад решить эту проблему.
ruffin 3.01.2019 21:51:27

Некоторые операторы в JavaScript выполняют неявные преобразования типов, а иногда используются для преобразования типов.

Унарный !оператор преобразует свой операнд в логическое значение и отрицает его.

Этот факт приводит к следующей идиоме, которую вы можете увидеть в своем исходном коде:

!!x // Same as Boolean(x). Note double exclamation mark
3
1.07.2015 07:29:12

!!x это сокращение для Boolean(x)

Первый удар заставляет двигатель js работать, Boolean(x)но также имеет побочный эффект инвертирования значения. Таким образом, второй удар отменяет побочный эффект.

8
4.12.2015 12:50:49

Операторы ifand whileи ?оператор используют значения истинности, чтобы определить, какую ветвь кода запустить. Например, нулевые и 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.

10
6.03.2016 14:46:50

Я думаю, стоит упомянуть, что условие в сочетании с логическим И / ИЛИ не будет возвращать логическое значение, но последний успех или первый сбой в случае && и первый успех или последний сбой в случае || цепи условий.

res = (1 && 2); // res is 2
res = (true && alert) // res is function alert()
res = ('foo' || alert) // res is 'foo'

Чтобы привести условие к истинному логическому литералу, мы можем использовать двойное отрицание:

res = !!(1 && 2); // res is true
res = !!(true && alert) // res is true
res = !!('foo' || alert) // res is true
18
25.05.2016 10:18:34

Используйте логический оператор not два раза,
это значит! True = false
и !! true = true

3
15.07.2016 10:25:01

Я просто хотел добавить, что

if(variableThing){
  // do something
}

такой же как

if(!!variableThing){
  // do something
}

Но это может быть проблемой, когда что-то не определено.

// a === undefined, b is an empty object (eg. b.asdf === undefined)
var a, b = {};

// Both of these give error a.foo is not defined etc.
// you'd see the same behavior for !!a.foo and !!b.foo.bar

a.foo 
b.foo.bar

// This works -- these return undefined

a && a.foo
b.foo && b.foo.bar
b && b.foo && b.foo.bar

Хитрость здесь в том, что цепочка &&s вернет первое найденное значение Falsey - и это может быть передано в оператор if и т. Д. Поэтому, если b.foo не определен, он вернет undefined и пропустит b.foo.barоператор, и мы не получим ошибка.

Вышеприведенный возврат не определен, но если у вас есть пустая строка, false, null, 0, undefined, эти значения вернутся, и как только мы встретим их в цепочке, - []и {}они оба будут «правдивыми», и мы продолжим в так называемом » && chain "к следующему значению справа.

PS Еще один способ сделать то же самое (b || {}).foo, потому что, если b не определено, то b || {}будет {}, и вы будете получать доступ к значению в пустом объекте (без ошибок) вместо того, чтобы пытаться получить доступ к значению в пределах «неопределенного» (вызывает ошибку ). Итак, так (b || {}).fooже, как b && b.fooи так ((b || {}).foo || {}).barже, как b && b.foo && b.foo.bar.

6
25.06.2019 18:35:35
Хороший вопрос - изменил мой ответ. Это происходит только на объекте, когда он вложен в три уровня глубиной, потому что, как вы сказали ({}).anything, дастundefined
Ryan Taylor 10.01.2017 17:36:42

Увидев все эти замечательные ответы, я хотел бы добавить еще одну причину использования !!. В настоящее время я работаю в Angular 2-4 (TypeScript) и хочу вернуть логическое значение, как falseесли бы мой пользователь не проходил аутентификацию. Если он не аутентифицирован, токен-строка будет nullили "". Я могу сделать это с помощью следующего блока кода:

public isAuthenticated(): boolean {
   return !!this.getToken();
}
5
29.03.2017 07:15:21

!!похоже на использование булева конструктора или, возможно, больше похоже на булеву функцию.

console.log(Boolean(null)); // Preffered over the Boolean object

console.log(new Boolean(null).valueOf()); // Not recommended for coverting non-boolean values

console.log(!!null); // A hacky way to omit calling the Boolean function, but essentially does the same thing. 


// The context you saw earlier (your example)
var vertical;

function Example(vertical)
{
        this.vertical = vertical !== undefined ? !!vertical : 
        this.vertical; 
        // Let's break it down: If vertical is strictly not undefined, return the boolean value of vertical and set it to this.vertical. If not, don't set a value for this.vertical (just ignore it and set it back to what it was before; in this case, nothing).   

        return this.vertical;
}

console.log( "\n---------------------" )

// vertical is currently undefined

console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

vertical = 12.5; // set vertical to 12.5, a truthy value.
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical which happens to be true anyway
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

vertical = -0; // set vertical to -0, a falsey value.
console.log(new Example(vertical).vertical); // The falsey or truthy value of this.vertical which happens to be false either way
console.log(!!new Example(vertical).vertical); // Coerced value of this.vertical

Значения , Falsey в JavaScript принуждать год до ЛЖИ и truthy значений , принуждать к действительности. Ложные и истинные значения также могут использоваться в ifвыражениях и будут по существу «отображаться» на их соответствующие логические значения. Однако вам, вероятно, не придется часто использовать правильные логические значения, так как они в основном отличаются в выходных данных (возвращаемые значения).

Хотя это может показаться похожим на приведение, в действительности это скорее всего простое совпадение, и оно не «построено» или специально сделано для и не похоже на логическое приведение. Так что давайте не будем так это называть.


Почему и как это работает

Чтобы быть кратким, это выглядит примерно так: ! ( !null ). Принимая во внимание, что nullэто ложь , так !nullбыло бы правдой . Тогда !trueбудет ложным, и это будет по существу инвертировать обратно к тому, что было раньше, за исключением этого времени как правильное логическое значение (или даже наоборот с истинными значениями, такими как {}или 1).


Возвращаясь к вашему примеру

В целом, контекст, который вы видели, просто корректируется в this.verticalзависимости от того, определен или нет vertical, и если так; для него будет установлено результирующее логическое значение вертикали, иначе оно не изменится. Другими словами, если verticalэто определено; this.verticalбудет установлено его логическое значение, в противном случае он останется прежним. Я думаю, что это сам по себе пример того, как вы будете использовать !!, и что он делает.


Пример вертикального ввода / вывода

Запустите этот пример и возитесь с вертикальным значением на входе. Посмотрите, к чему приводит результат, чтобы вы могли полностью понять код вашего контекста. Во входных данных введите любое допустимое значение JavaScript. Не забудьте включить цитаты, если вы тестируете строку. Не обращайте слишком много внимания на CSS и HTML-код, просто запустите этот фрагмент и поэкспериментируйте с ним. Тем не менее, вы можете захотеть взглянуть на не связанный с DOM код JavaScript, хотя (использование конструктора примера и вертикальной переменной).

var vertical = document.getElementById("vertical");
var p = document.getElementById("result");

function Example(vertical)
{
        this.vertical = vertical !== undefined ? !!vertical : 
        this.vertical;   

        return this.vertical;
}

document.getElementById("run").onclick = function()
{

  p.innerHTML = !!( new Example(eval(vertical.value)).vertical );
  
}
input
{
  text-align: center;
  width: 5em;
} 

button 
{
  margin: 15.5px;
  width: 14em;
  height: 3.4em;
  color: blue;
}

var 
{
  color: purple;
}

p {
  margin: 15px;
}

span.comment {
  color: brown;
}
<!--Vertical I/O Example-->
<h4>Vertical Example</h4>
<code id="code"><var class="var">var</var> vertical = <input type="text" id="vertical" maxlength="9" />; <span class="comment">// enter any valid javascript value</span></code>
<br />
<button id="run">Run</button>
<p id="result">...</p>

2
17.04.2017 16:32:12

!!он использует NOTоперацию дважды вместе, !преобразует значение в a booleanи переворачивает его, вот простой пример, чтобы увидеть, как !!работает:

Во-первых, место у вас есть:

var zero = 0;

Затем вы это сделаете !0, он будет преобразован в логическое значение и будет оценен trueкак 0 falsy, так что вы получите обратное значение и преобразуете в логическое значение, так что оно будет оценено как true.

!zero; //true

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

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

Так что это похоже на использование Booleanфункции в javascript, но простой и более короткий способ преобразования значения в логическое значение:

var zero = 0;
!!zero; //false
17
8.07.2019 12:45:31