Что!! (не нет) оператор в JavaScript?
Я видел некоторый код, который, кажется, использует оператор, который я не распознаю, в виде двух восклицательных знаков, например так: !!
, Может кто-нибудь сказать, пожалуйста, что делает этот оператор?
Контекст, в котором я видел это, был,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
43 ответа
Принуждают oObject
логическое. Если это было фальси (например, 0, null
, undefined
и т. д.), это будет false
, иначе, true
,
!oObject //Inverted boolean
!!oObject //Non inverted boolean so true boolean representation
Так !!
это не оператор, это просто !
оператор дважды.
Пример из реальной жизни "Test IE version":
let isIE8 = false;
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
Это ужасно непонятный способ преобразования типов.
!
нет Так !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);
!!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!
Заварите немного чая:
!!
не оператор. Это двойное использование !
- который является логическим оператором "не".
Теоретически:
!
определяет "правду" о том, что значение не является:
Правда в том, что
false
не являетсяtrue
(вот почему!false
результаты вtrue
)Правда в том, что
true
не являетсяfalse
(вот почему!true
результаты вfalse
)
!!
определяет "правду" о том, что значение не является:
Правда в том, что
true
не нетtrue
(вот почему!!true
результаты вtrue
)Правда в том, что
false
не нетfalse
(вот почему!!false
результаты вfalse
)
Что мы хотим определить при сравнении, так это "правда" о значении ссылки, а не о ценности самой ссылки. Существует вариант использования, в котором мы можем захотеть узнать правду о значении, даже если мы ожидаем, что значение будет false
(или ложь), или если мы ожидаем, что значение не будет typeof boolean
,
На практике:
Рассмотрим краткую функцию, которая обнаруживает функциональные возможности (и в данном случае совместимость с платформой) посредством динамической типизации (так называемая "утиная типизация"). Мы хотим написать функцию, которая возвращает true
если браузер пользователя поддерживает HTML5 <audio>
элемент, но мы не хотим, чтобы функция выдавала ошибку, если <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
Каждая функция принимает аргумент для <tag>
и 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
из небулева, возможно, неопределенное значение действительно с помощью !!
, Надеюсь, это смехотворно проясняет.
!!
преобразует значение справа от него в эквивалентное логическое значение. (Подумайте о том, как бедняк "набирает текст"). Его намерение обычно состоит в том, чтобы донести до читателя, что коду не важно, какое значение находится в переменной, а какое это значение "истинности".
!!foo
применяет унарный оператор not дважды и используется для приведения к логическому типу, аналогичному использованию унарного плюса +foo
привести к числу и объединить пустую строку ''+foo
бросать в строку.
Вместо этих хаков вы также можете использовать функции конструктора, соответствующие примитивным типам (без использования new
) явно приводить значения, т.е.
Boolean(foo) === !!foo
Number(foo) === +foo
String(foo) === ''+foo
Так много ответов делают половину работы. Да, !!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 г.:
Сторонние библиотеки, которые ожидают явные логические значения
Вот интересный случай... !!
может быть полезно, когда сторонние библиотеки ожидают явных логических значений.
Например, 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>}
(или что-то менее надуманное).
Одно исправление включает в себя взрыв, который принуждает
0
в!!0
, которыйfalse
:{!!messageCount && <div>You have messages!</div>}
Документы JSX предполагают, что вы должны быть более явными, писать код с само комментированием и использовать сравнение для принудительного использования в логическом выражении.
{messageCount > 0 && <div>You have messages!</div>}
Мне удобнее справляться с ложностью с тройной -
{messageCount ? <div>You have messages!</div> : false}
Имейте в виду, что это соглашение JSX, а не то, которое присуще JavaScript.
Но если вы видите странное 0
s в вашем рендеринге JSX, подумайте о свободном фальшивом управлении.
Это просто логический оператор NOT, дважды - он используется для преобразования чего-либо в логическое значение, например:
true === !!10
false === !!0
Кажется, что !!
оператор приводит к двойному отрицанию.
var foo = "Hello World!";
!foo // Result: false
!!foo // Result: true
!!
он использует NOT
операция дважды вместе, !
преобразовать значение в boolean
и наоборот, вот простой пример, чтобы увидеть, как !!
работает:
Во-первых, место у вас есть:
var zero = 0;
Тогда вы делаете !0
, он будет преобразован в логическое значение и будет оценен как true
потому что 0 falsy
, так что вы получите обратное значение и преобразовать в логическое значение, так что оно будет оценено как true
,
!zero; //true
но нам не нужна обратная логическая версия значения, поэтому мы можем отменить ее снова, чтобы получить наш результат! Вот почему мы используем другой !
,
В принципе, !!
убедитесь, что мы получаем логическое значение, а не ложное, правдивое или строковое и т. д.
Так что это похоже на использование Boolean
Функция в JavaScript, но простой и короткий способ преобразования значения в логическое значение:
var zero = 0;
!!zero; //false
Имитирует поведение Boolean()
литейная функция. Первый NOT
возвращает логическое значение независимо от того, какой операнд ему дан. Второй NOT
отрицает, что Boolean
значение и так дает true
Булево значение переменной. Конечный результат такой же, как при использовании Boolean()
функция на значение.
Это двойной not
операция. Первый !
преобразует значение в логическое значение и инвертирует его логическое значение. Второй !
инвертирует логическое значение обратно.
! is "boolean not", что по существу типизирует значение "enable" к его логическому противоположному значению. Второй! переворачивает это значение. Так, !!enable
означает "не включить", давая вам значение enable
как логическое.
Я думаю, стоит упомянуть, что условие в сочетании с логическим И / ИЛИ не будет возвращать логическое значение, но последний успех или первый сбой в случае && и первый успех или последний сбой в случае || цепочки условий.
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
Это не один оператор, это два. Это эквивалентно следующему и является быстрым способом приведения значения к логическому значению.
val.enabled = !(!enable);
!!
Конструкция - это простой способ превратить любое выражение JavaScript в его логический эквивалент.
Например: !!"he shot me down" === true
а также !!0 === false
,
Это заставляет все вещи к булеву.
Например:
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
Я подозреваю, что это остаток от C++, где люди переопределяют! оператор, но не оператор bool.
Таким образом, чтобы получить отрицательный (или положительный) ответ в этом случае, вам сначала нужно использовать! оператор, чтобы получить логическое значение, но если вы хотите проверить положительный случай, используйте!!.
if
а также while
заявления и ?
оператор использует значения истинности, чтобы определить, какую ветвь кода запустить. Например, ноль и числа NaN и пустая строка являются ложными, но другие числа и строки являются истинными. Объекты истинны, но неопределенное значение и null
оба ложные.
Оператор двойного отрицания !!
вычисляет истинное значение стоимости. Это на самом деле два оператора, где !!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
или неопределенное значение, такое как определение функции браузера.
Другое использование, о котором я упоминал в ответе о соответствующем С !!
оператор, с инструментами "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
выполняет логическое И (истина, если обе стороны верны), и a & b
выполняет побитовое И. a || b
выполняет логическое ИЛИ (истина, если хотя бы одно из них истинно), и a | b
выполняет побитовое ИЛИ. Там есть побитовый XOR (исключающее ИЛИ) как a ^ b
, но нет встроенного оператора для логического XOR (true, если истинна только одна сторона). Например, вы можете разрешить пользователю вводить текст точно в одно из двух полей. Что вы можете сделать, так это преобразовать каждое значение в истинное и сравнить их: !!x !== !!y
,
На этот вопрос был дан довольно подробный ответ, но я хотел бы добавить ответ, который, я надеюсь, будет максимально упрощенным, что придает смысл!! так просто понять, как это может быть.
Поскольку в 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) {}
ОБА вернет истину, как и ожидалось.
Двойное логическое отрицание. Часто используется для проверки, если значение не определено.
Я просто хотел добавить, что
if(variableThing){
// do something
}
такой же как
if(!!variableThing){
// do something
}
Но это может быть проблемой, когда что-то не определено.
// a is undefined, b is empty object.
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, эти значения вернутся, и как только мы встретим их в цепочке - []
а также {}
оба правдивы.
!!x
это сокращение для Boolean(x)
Первый удар заставляет двигатель JS работать Boolean(x)
но также имеет побочный эффект инвертирования значения. Таким образом, второй удар отменяет побочный эффект.
Тонны отличных ответов здесь, но если вы прочитали это далеко, это помогло мне "получить это". Откройте консоль в Chrome (и т. Д.) И начните вводить:
!(!(1))
!(!(0))
!(!('truthy'))
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)
Естественно, это все равно, что просто набирать!!someThing, но добавленные скобки могут помочь сделать его более понятным.
Увидев все эти замечательные ответы, я хотел бы добавить еще одну причину использования !!
, В настоящее время я работаю в Angular 2-4 (TypeScript), и я хочу вернуть логическое значение как false
когда мой пользователь не аутентифицирован. Если он не аутентифицирован, токен-строка будет null
или же ""
, Я могу сделать это с помощью следующего блока кода:
public isAuthenticated(): boolean {
return !!this.getToken();
}
Вот кусок кода от угловой 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 был бы верным и еще одним! это было бы ложным
Возвращает логическое значение переменной.
Вместо, 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
Используйте логический оператор не два раза
это значит!true= false
и!! правда = правда
Важно помнить оценки в JavaScript и в нем :
Все, что имеет значение "Value" (а именно правдиво), например:
-
101
, -
3.1415
, -
-11
, -
"Lucky Brain"
, -
new Object()
- и, конечно же,
true
-
Все, что не имеет значения «Value», является (а именно ложным), например:
-
0
, -
-0
, -
""
(пустой строкой), -
undefined
, -
null
, -
NaN
(не число) - и, конечно же,
false
-
Применение оператора « логическое не » (
!
) оценивает операнд, преобразуя его в, а затем отрицая. Применение его дважды приведет к отрицанию отрицания, эффективно преобразовав значение в. Отсутствие оператора будет просто обычным присвоением точного значения. Примеры:
var value = 23; // number
var valueAsNegatedBoolean = !value; // boolean falsy (because 23 is truthy)
var valueAsBoolean = !!value; // boolean truthy
var copyOfValue = value; // number 23
var value2 = 0;
var value2AsNegatedBoolean = !value2; // boolean truthy (because 0 is falsy)
var value2AsBoolean = !!value2; // boolean falsy
var copyOfValue2 = value2; // number 0
-
value2 = value;
назначает точный объект, даже если это не такvalue2
не обязательно в конечном итоге. -
value2 = !!value;
назначает гарантированныйboolean
в результате двойного отрицания операндаvalue
и это эквивалентно следующему, но намного короче и читабельнее: