Вопрос: Что это !! (не) оператор в JavaScript?


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

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

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

2259


источник


Ответы:


принуждают oObjectдля boolean. Если он был ложным (например, 0, null, undefinedи т. д.), это будет false, в противном случае, true,

!oObject  //Inverted boolean
!!oObject //Non inverted boolean so true boolean representation

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

Пример реального мира «Версия тестового IE»:

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 null  

но если вы ⇒

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

2010



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

!является НЕ , Так !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);

719



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

          !!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!

367



Заварить чай:

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


В теории:

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

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

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


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

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

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


То, что мы хотим определить в сравнении, - это «правда», около значение ссылки, а не значение сама ссылка. Существует прецедент, где мы, возможно, захотим узнать правду о значении, даже если мы ожидаем, что значение будет false(или false), или если мы ожидаем, что значение не будет 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из небулевого, возможно неопределенного значения, действительно, используя !!, Надеюсь, это смешно очистит его.


124



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


86



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

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

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo

58



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

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

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

То есть...

  • 0 === falseявляется false,
  • !!0 === falseявляется true,

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

См. «== и! =» Из Направления JSLint (примечание: Crockford немного перемещает свой сайт, эта ссылка может умереть в какой-то момент) немного о том, почему:

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

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

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

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

сказать
(!foo)

Обратите внимание, что есть некоторые неинтуитивные случаи где булевое будет передано в число ( trueотбрасывается 1а также falseв 0) при сравнении булевых чисел с числом. В этом случае, !!может быть умственно полезным. Хотя, опять же, это случаи, когда вы сравниваете не-логическое значение с жестким типизированным логическим выражением, которое является imo, серьезной ошибкой. 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и это правда! Та же правдивость! (В этом случае оба «имеют правдоподобие фальши»).

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

Я не могу придумать отличный, непринужденный случай использования для этого. Возможно, у вас есть «связанные» поля в форме?

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коллекция.


EDIT 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в вашем рендеринге JSX, подумайте об управлении фальшими.


43



It's just the logical NOT operator, twice - it's used to convert something to boolean, e.g.:

true === !!10

false === !!0

42



It converts the suffix to a Boolean value.


28



It's a double not operation. The first ! converts the value to boolean and inverts its logical value. The second ! inverts the logical value back.


21



It simulates the behavior of the Boolean() casting function. The first NOT returns a Boolean value no matter what operand it is given. The second NOT negates that Boolean value and so gives the true Boolean value of a variable. The end result is the same as using the Boolean() function on a value.


21



It seems that the !! operator results in a double negation.

var foo = "Hello World!";

!foo // Result: false
!!foo // Result: true

18