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

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

this.vertical = vertical !== undefined ? !!vertical : this.vertical;
3039
Hexagon Theory 24 Апр 2009 в 12:13

28 ответов

Лучший ответ

Преобразует Object в boolean. Если это была ложь (например, 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
2696
janniks 7 Фев 2020 в 11:40

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

23
Prakash 23 Мар 2011 в 11:53

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

! - это НЕ . Итак, !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);
845
Lightness Races in Orbit 26 Сен 2011 в 14:08

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

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

10
Darren Clark 24 Апр 2009 в 08:33

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

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

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

8
Warren Davis 24 Апр 2014 в 13:05

Это заставляет все вещи к булеву.

Например:

console.log(undefined); // -> undefined
console.log(!undefined); // -> true
console.log(!!undefined); // -> false

console.log('abc'); // -> abc
console.log(!'abc'); // -> false
console.log(!!'abc'); // -> true

console.log(0 === false); // -> undefined
console.log(!0 === false); // -> false
console.log(!!0 === false); // -> true
7
Sathyam Lokare 6 Сен 2018 в 02:02

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

8
Sergey Ilinsky 2 Дек 2010 в 20:21

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

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

8
Greg Gum 4 Дек 2015 в 12:50

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

true === !!10

false === !!0
53
Greg 24 Апр 2009 в 08:18

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

20
Annika Backstrom 10 Сен 2009 в 17:29

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

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

15
user4642212 10 Сен 2015 в 08:20

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

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

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo
70
Christoph 10 Сен 2009 в 21:15

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

101
Crescent Fresh 10 Сен 2009 в 17:26

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

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
GreQ 25 Май 2016 в 10:18

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

Поскольку в javascript есть значения, которые называются «правдивыми» и «ложными» значениями, существуют выражения, которые при оценке в других выражениях приведут к условию «истина» или «ложь», даже если проверяемое значение или выражение на самом деле не true или false .

Например:

if (document.getElementById('myElement')) {
    // code block
}

Если этот элемент действительно существует, выражение будет оцениваться как true, и блок кода будет выполнен.

Однако:

if (document.getElementById('myElement') == true) {
    // code block
}

... НЕ приведет к истинному условию, и блок кода не будет выполнен, даже если элемент существует.

Зачем? Потому что document.getElementById() является «истинным» выражением, которое будет оценено как истинное в этом if() выражении, но это не фактическое логическое значение true.

Двойное «не» в этом случае довольно просто. Это просто два not спина к спине.

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

if (!!document.getElementById('myElement')) {}

И

if (!!document.getElementById('myElement') == true) {}

ОБА вернет истину, как и ожидалось.

6
Kirby L. Wallace 10 Мар 2019 в 18:43

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

public isAuthenticated(): boolean {
   return !!this.getToken();
}
5
Wouter Vanherck 29 Мар 2017 в 07:15

Вот кусок кода от угловой 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
JeevanReddy Avanaganti 4 Мар 2015 в 08:25

Операторы if и 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 верно.

Оператор !! заверяет инструмент lint в том, что вы написали именно то, что имели в виду: выполните эту операцию, а затем примите истинное значение результата.

Третье использование - создание логического XOR и логического XNOR. И в C, и в JavaScript a && b выполняет логическое AND (true, если обе стороны верны), а a & b выполняет побитовое AND. a || b выполняет логическое ИЛИ (true, если хотя бы одно из них истинно), а a | b выполняет побитовое ИЛИ. Существует побитовое XOR (исключающее ИЛИ) как a ^ b, но нет встроенного оператора для логического XOR (true, если истинна только одна сторона). Например, вы можете разрешить пользователю вводить текст точно в одно из двух полей. Что вы можете сделать, это преобразовать каждое значение в истинное и сравнить их: !!x !== !!y.

10
Damian Yerrick 6 Мар 2016 в 14:46

Возвращает логическое значение переменной.

Вместо этого можно использовать Boolean класс.

(пожалуйста, прочтите описание кода)

var X = "test"; // X value is "test" as a String value
var booleanX = !!X // booleanX is `true` as a Boolean value beacuse non-empty strings evaluates as `true` in boolean
var whatIsXValueInBoolean = Boolean(X) // whatIsXValueInBoolean is `true` again
console.log(Boolean(X) === !!X) // writes `true`

А именно, Boolean(X) = !!X используется.

Пожалуйста, проверьте фрагмент кода ниже

let a = 0
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a) // writes '0 is NOT true in boolean' value as boolean - So that's true.In boolean 0 means false and 1 means true.
console.log("!!a: ", !!a) // writes 0 value in boolean. 0 means false.
console.log("Boolean(a): ", Boolean(a)) // equals to `!!a`
console.log("\n") // newline

a = 1
console.log("a: ", a)
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes 1 value in boolean
console.log("\n") // newline

a = ""
console.log("a: ", a)
console.log("!a: ", !a) // writes '"" is NOT true in boolean' value as boolean - So that's true.In boolean empty strings, null and undefined values mean false and if there is a string it means true.
console.log("!!a: ", !!a) // writes "" value in boolean
console.log("\n") // newline

a = "test"
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes "test" value in boolean

console.log("Boolean(a) === !!a: ", Boolean(a) === !!a) // writes true
3
efkan 11 Июл 2017 в 07:22

!!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!
442
Salman A 24 Окт 2015 в 21:00

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

3
Abhay Dixit 15 Июл 2016 в 10:25

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

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


Теоретически:

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

  • Правда в том, что false не является true (поэтому результаты !false в true )

  • Правда в том, что true не является false (поэтому результаты !true в false )


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

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

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


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


На практике:

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

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

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

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

// 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 из небулева, возможно, неопределенного значения действительно является использование {{X1} } . Надеюсь, это смехотворно проясняет.

153
Benny 22 Фев 2013 в 23:45

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

val.enabled = !(!enable);
14
Justin Johnson 10 Сен 2009 в 21:19

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

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

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

!!x // Same as Boolean(x). Note double exclamation mark
3
GibboK 1 Июл 2015 в 07:29

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

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

var zero = 0;

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

!zero; //true

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

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

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

var zero = 0;
!!zero; //false
17
Alireza 8 Июл 2019 в 12:45

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

26
Bill the Lizard 10 Сен 2009 в 17:28

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

var foo = "Hello World!";

!foo // Result: false
!!foo // Result: true
23
Lightness Races in Orbit 9 Ноя 2011 в 10:35

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

32
Paul McMillan 29 Окт 2009 в 21:22