Что !! (не нет) оператор в JavaScript? - PullRequest
2723 голосов
/ 24 апреля 2009

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

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

this.vertical = vertical !== undefined ? !!vertical : this.vertical;

Ответы [ 35 ]

7 голосов
/ 24 апреля 2014

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

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

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

7 голосов
/ 04 декабря 2015

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

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

5 голосов
/ 25 июля 2018

Это заставляет все вещи логические.

Например:

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
4 голосов
/ 04 марта 2015

вот кусок кода от угловой 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 будет верным и еще одним! это было бы ложным

3 голосов
/ 10 марта 2019

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

Поскольку 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) {}

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

3 голосов
/ 11 июля 2017

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

Вместо этого можно использовать 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 голосов
/ 29 марта 2017

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

public isAuthenticated(): boolean {
   return !!this.getToken();
}
3 голосов
/ 20 октября 2016

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

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, эти значения вернутся, и как только мы встретим их в цепочке - [] и {} оба будут верны.

3 голосов
/ 01 июля 2015

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

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

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

!!x // Same as Boolean(x). Note double exclamation mark
2 голосов
/ 17 апреля 2017

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

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

ложные значения в javascript принудительные до ложные и истинные значения принудительные до истинные . Значения Falsey и truey также могут использоваться в операторах if и будут по существу "отображаться" в их соответствующие логические значения. Однако вам, вероятно, не придется часто использовать правильные логические значения, так как они в основном отличаются в выходных данных (возвращаемые значения).

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

<ч />

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

Чтобы быть кратким, это выглядит примерно так: ! ( !null ). Принимая во внимание, что null - это Falsey , поэтому !null будет true . Тогда !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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...