O que é !! (não não) operador em JavaScript?


3108

Eu vi algum código que parece usar um operador que não reconheço, na forma de dois pontos de exclamação, assim: !!. Alguém pode me dizer o que esse operador faz?

O contexto em que eu vi isso foi,

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

946
Lembre-se disso por "bang, bang, você é booleano"
Gus

75
Apenas para constar, não faça o que é citado lá. Faça if(vertical !== undefined) this.vertical = Boolean(vertical);- é muito mais claro e claro o que está acontecendo, não requer atribuição desnecessária, é totalmente padrão e é tão rápido (no FF e no Chrome atuais ) jsperf.com/boolean-conversion-speed .
Phil H

73
!! não é um operador. É apenas o! operador duas vezes.
Vivek

11
Apenas para o registro, Boolean(5/0)não é o mesmo que!!5/0
schabluk 12/02/2015

63
@schabluk, para constar, a ordem das operações é a razão pela qual !!5/0produz, Infinitye não truecomo produzido por Boolean(5/0). !!5/0é equivalente a (!!5)/0- aka true/0- devido ao fato de o !operador ter uma precedência mais alta que o /operador. Se você deseja fazer um booleano 5/0usando um golpe duplo, precisará usá-lo !!(5/0).
matty 24/05

Respostas:


2748

Converte Objectpara boolean. Se fosse Falsey (por exemplo 0, null, undefined, etc.), que vai ser false, de outra forma, true.

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

Portanto, !!não é um operador, é apenas o !operador duas vezes.

Exemplo do mundo real "Test IE version":

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

Se você ⇒

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

Mas se você ⇒

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

123
Ele converte um não-booleano em um booleano invertido (por exemplo,! 5 seria falso, uma vez que 5 é um valor não-falso em JS) e, em seguida, inverte booleanos para que você obtenha o valor original como um booleano (então !! 5 seria seja verdadeiro).
24310 Chuck

111
Uma maneira fácil de descrevê-lo é: Boolean (5) === !! 5; Mesmo elenco, menos personagens.
Micah Snyder

39
Isso é usado para converter valores de verdade em booleano true e valores de falsy muito booleanos false.
Thetoolman

13
@Micah Snyder, tenha cuidado para que, no JavaScript, seja melhor usar primitivas booleanas em vez de criar objetos que encaixotem booleanos com o novo Boolean (). Aqui está um exemplo para ver a diferença: jsfiddle.net/eekbu
victorvartan

4
Tanto quanto eu sei, esse padrão de bang-bang não é útil dentro de um if (... _ declaração;. Apenas em uma instrução de retorno de uma função que deve retornar um boolean
RDS

854

É uma maneira horrivelmente obscura de fazer uma conversão de tipo.

!NÃO é . Então !trueé falsee !falseé true. !0é truee !1é false.

Então você está convertendo um valor para um booleano, invertendo-o e invertendo-o novamente.

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

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

// And finally, much easier to understand:
val.enabled = (userId != 0);

74
!! falso = falso. !! verdadeiro = true
cllpse

89
A variante "muito mais fácil de entender" é realmente muito mais fácil de entender aqui? A verificação contra 0 não é uma verificação real contra 0, mas uma verificação contra a lista um tanto estranha de valores que o Javascript considera igual a 0. userId ? true : false deixa mais claro que há uma conversão em andamento e lida com o caso em que o valor de userId pode ter sido explicitamente definido comoundefined
Ben Regenspan 13/10/10

54
Meu cérebro não tem nenhum problema !!varpara decodificar em Boolean(var).. e !!é mais rápido (menos instruções para processar) e mais curto que as alternativas.
adamJLev

7
O @RickyClarkson é principalmente para facilitar a leitura, pois, sintaticamente, não é necessário. Alguns usam a convenção de sempre agrupar uma condicional entre parênteses para diferenciá-la do resto da expressão.
Dave Rager

8
Eu discordo disso. userId != 0é verdadeiro para null, NaNe undefined, mas falso para false. Se você deseja exatamente esse comportamento, provavelmente deve ser explícito. Mas, mesmo que funcionasse exatamente da mesma forma !!userId, não está claro se você deseja que esses valores sejam falsos aqui ou se apenas não considerou as regras de conversão de tipo do Javascript.
Phill

449

!!exprretorna um valor booleano ( trueou false) dependendo da veracidade da expressão. Faz mais sentido quando usado em tipos não booleanos. Considere estes exemplos, especialmente o terceiro exemplo e seguintes:

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

63
Vale notar:!!new Boolean(false) // true
Camilo Martin

43
... Mas também!!Boolean(false) // false
Camilo Martin

97
new Boolean(false)é um objeto e um objeto é verdadeiro, mesmo que contenha um valor falso!
Salman A

3
Sim, eu sei, mas considerar o fato de que a maioria dos construtores nativos ( String, Number, Date, etc) são destinadas a ser exigível como funções muito, mas, neste caso, o resultado é diferente!
Camilo Martin

4
@CamiloMartin: acabei de perceber que new Boolean(false)retorna um objecttempo Boolean(false)retorna o primitivo false . Espero que isso faça sentido.
precisa

155

Prepare um pouco de chá:

!!não é um operador. É o uso duplo de !- que é o operador lógico "não".


Em teoria:

! determina a "verdade" do que não é um valor:

  • A verdade é que falsenão é true(é por isso que !falseresulta true)

  • A verdade é que truenão é false(é por isso que !trueresulta false)


!!determina a "verdade" do que não é um valor :

  • A verdade é que truenão é true (é por isso que !!trueresulta true)

  • A verdade é que falsenão é false (é por isso que !!falseresulta false)


O que desejamos determinar na comparação é a "verdade" sobre o valor de uma referência, não o valor da própria referência. Há um caso de uso em que podemos querer saber a verdade sobre um valor, mesmo se esperamos que o valor seja false(ou falsey), ou se esperamos que o valor não seja do tipo typeof boolean.


Na prática:

Considere uma função concisa que detecta a funcionalidade do recurso (e, neste caso, a compatibilidade da plataforma) por meio de digitação dinâmica (também conhecida como "digitação de pato"). Queremos escrever uma função que retorne truese o navegador de um usuário suportar o <audio>elemento HTML5 , mas não queremos que a função gere um erro se <audio>for indefinida; e não queremos usar try ... catchpara lidar com possíveis erros (porque eles são brutos); e também não queremos usar uma verificação dentro da função que não revele consistentemente a verdade sobre o recurso (por exemplo, document.createElement('audio')ainda criará um elemento chamado <audio>mesmo se o HTML5 <audio>não for suportado).


Aqui estão as três abordagens:

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

Cada função aceita um argumento para a <tag>e an attributepara procurar, mas cada um retorna valores diferentes com base no que as comparações determinam.

Mas espere, tem mais!

Alguns de vocês provavelmente notaram que, neste exemplo específico, pode-se simplesmente verificar uma propriedade usando os meios um pouco mais eficientes de verificar se o objeto em questão tem uma propriedade. Existem duas maneiras de fazer isso:

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

Nós discordamos ...

Por mais raras que sejam essas situações, pode haver alguns cenários nos quais o meio mais conciso, com melhor desempenho e, portanto, o mais preferido para obter trueum valor não booleano e possivelmente indefinido é de fato usando !!. Espero que isso ridiculamente esclarece.


1
resposta totalmente incrível, mas não vejo a utilidade do !! construir. Como uma if()instrução já lança a expressão como booleana, a conversão explícita do valor de retorno de uma função de teste para booleana é redundante - uma vez que "veracidade" === é verdadeira no que diz respeito a uma if()instrução. Ou estou perdendo um cenário em que você PRECISA que uma expressão de verdade seja realmente booleana true?
Tom Auger

1
As if()instruções @TomAuger convertem booleano contra valores falsey, mas dizem que você deseja realmente definir um sinalizador booleano em um objeto - ele não será convertido como uma if()declaração. Por exemplo object.hasTheThing = !!castTheReturnValToBoolNoMatterWhat(), definiria trueou em falsevez do valor de retorno real. Outro exemplo é talvez todos os administradores são idda 0e não-administradores são ID 1ou superior. Para truesaber se alguém não é um administrador, você poderia fazer person.isNotAdmin = !!admin.id. Poucos casos de uso, mas é conciso quando existe.
Benny

103

!!converte o valor à direita dele em seu valor booleano equivalente. (Pense na maneira do pobre homem de "moldar"). Sua intenção é geralmente transmitir ao leitor que o código não se importa com o valor da variável, mas com o valor da "verdade" .


4
Ou, no caso de um valor booleano à direita, ele não faz nada.
11339 Daniel A. White

3
@ Daniel: !ainda vira o valor para a direita. No caso de um booleano, o mais à direita !nega o valor, enquanto o mais à esquerda !nega mais uma vez. O efeito líquido é que não há alterações, mas a maioria dos mecanismos gerará códigos operacionais para a dupla negação.
Crescent Fresh

Mas qual é o ponto? Se eu faço if(0){...Javascript já sabe que isso é falso. Por que é melhor dizer if(!!0){...?
CodyBugstein

o ponto é para variáveis ​​que você talvez não conheça seu conteúdo; se poderia ser um número inteiro ou uma sequência, um objeto ou nulo, indefinido, etc. Essa é uma maneira fácil de testar a existência.
precisa saber é o seguinte

71

!!fooaplica o operador unary not duas vezes e é usado para converter para o tipo booleano semelhante ao uso de unary plus +foopara converter para número e concatenar uma sequência vazia ''+foopara transmitir para sequência.

Em vez desses hacks, você também pode usar as funções construtoras correspondentes aos tipos primitivos ( sem usar new) para converter valores explicitamente, ou seja,

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

Mas você pode ter problemas com instanceof. new Boolean (1) instanceof Object -> true !! 1 instanceof Object -> false
Seamus

13
não, você não pode: observe que as funções construtoras são chamadas sem new- como explicitamente mencionado na minha resposta
Christoph

2
fantástico! Isso é útil para um pequeno hack quando você precisa avaliar cadeias com "0" como falso em vez de verdadeiro. (ou seja, ao ler valores de select, porque eles são lidos como String). Portanto, se você quiser considerar "0" como negativo (booleano falso), x="0"basta fazer: o x=!!+x; //falseque é o mesmo que Boolean(Number(x))Number (ou + x) converte a string "0" em 0, que é avaliada como false e, em seguida, booleano (!! x) o lança para booleano diretamente. Mole-mole!
precisa saber é

2
@DiegoDD por que você escolheria !!+xvs x !== "0"?
placeybordeaux

@placeybordeaux porque, por exemplo, você pode querer converter o valor e atribuí-lo a outra variável, independentemente de compará-lo a outra coisa ou não.
precisa saber é

67

Tantas respostas fazendo metade do trabalho. Sim, !!Xpoderia ser lido como "a veracidade de X [representada como um booleano]". Mas !!, na prática, não é tão importante para descobrir se uma única variável é (ou mesmo se muitas variáveis ​​são) verdadeiras ou falsas. !!myVar === trueé o mesmo que apenas myVar. Comparar !!Xcom um booleano "real" não é realmente útil.

O que você ganha !!é a capacidade de verificar a veracidade de várias variáveis entre si de uma maneira repetitiva, padronizada (e amigável ao JSLint).

Simplesmente lançando :(

Isso é...

  • 0 === falseé false.
  • !!0 === falseé true.

O exposto acima não é tão útil. if (!0)fornece os mesmos resultados que if (!!0 === false). Não consigo pensar em um bom argumento para converter uma variável em booleano e depois compará-lo com um "booleano" verdadeiro.

Veja "== e! =" Das instruções de JSLint (nota: Crockford está movendo seu site um pouco; esse link pode morrer em algum momento) para um pouco de por que:

Os operadores == e! = Digitam coerção antes de comparar. Isso é ruim porque faz com que '\ t \ r \ n' == 0 seja verdadeiro. Isso pode mascarar erros de tipo. O JSLint não pode determinar com segurança se == está sendo usado corretamente, portanto, é melhor não usar == e! = De todo e sempre usar os operadores === e! == mais confiáveis.

Se você se importa apenas que um valor seja verdadeiro ou falso, use o formato abreviado. Ao invés de
(foo != 0)

apenas diga
(foo)

e em vez de
(foo == 0)

dizer
(!foo)

Observe que existem alguns casos não intuitivos em que um booleano será convertido para um número ( trueé convertido para 1e falsepara 0) ao comparar um booleano com um número. Nesse caso, !!pode ser mentalmente útil. Embora, novamente, esses sejam casos em que você está comparando um não-booleano a um booleano digitado, o que é, imo, um erro grave. if (-1)ainda é o caminho a percorrer aqui.

╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
               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
╚═══════════════════════════════════════╩═══════════════════╩═══════════╝

E as coisas ficam ainda mais loucas, dependendo do seu motor. O WScript, por exemplo, ganha o prêmio.

function test()
{
    return (1 === 1);
}
WScript.echo(test());

Por causa de algum jive histórico do Windows , isso gera -1 em uma caixa de mensagem! Experimente em um prompt do cmd.exe e veja! Mas WScript.echo(-1 == test())ainda dá 0 ou WScript false. Desvie o olhar. É horrível.

Comparando a veracidade :)

Mas e se eu tiver dois valores, preciso verificar a mesma veracidade / falsidade?

Finja que temos myVar1 = 0;e myVar2 = undefined;.

  • myVar1 === myVar2é 0 === undefinede é obviamente falso.
  • !!myVar1 === !!myVar2é !!0 === !!undefinede é verdade! A mesma veracidade! (Nesse caso, ambos "têm uma veracidade de falsidade".)

Portanto, o único lugar em que você realmente precisaria usar "variáveis ​​de conversão booleana" seria se você tivesse uma situação em que está verificando se as duas variáveis ​​têm a mesma veracidade, certo? Ou seja, o uso !!se você precisa ver se dois vars são ambos truthy ou ambos Falsas (ou não), isto é, de igual (ou não) truthiness .

Não consigo pensar em um ótimo caso de uso não planejado para esse assunto de improviso. Talvez você tenha "vinculado" campos em um formulário?

if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
    errorObjects.spouse = "Please either enter a valid name AND age " 
        + "for your spouse or leave all spouse fields blank.";
}

Portanto, agora, se você tem uma verdade para os dois ou um falso para o nome e a idade do cônjuge, pode continuar. Caso contrário, você terá apenas um campo com um valor (ou um casamento arranjado muito cedo) e precisará criar um erro extra em sua errorObjectscoleção.


EDIT 24 Out 2017, 6 fev 19:

Bibliotecas de terceiros que esperam valores booleanos explícitos

Aqui está um caso interessante ... !!pode ser útil quando bibliotecas de terceiros esperam valores booleanos explícitos.

Por exemplo, False em JSX (React) tem um significado especial que não é acionado por simples falsidade. Se você tentou retornar algo como o seguinte em seu JSX, esperando um int em messageCount...

{messageCount && <div>You have messages!</div>}

... você ficará surpreso ao ver Reativar renderização 0quando não houver mensagens. Você deve retornar explicitamente false para que o JSX não processe. A declaração acima retorna 0, que JSX processa felizmente, como deveria. Não se pode dizer que você não teve Count: {messageCount && <div>Get your count to zero!</div>}(ou algo menos artificial).

  • Uma correção envolve a bangbang, que coage 0em !!0, que é false:
    {!!messageCount && <div>You have messages!</div>}

  • Os documentos da JSX sugerem que você seja mais explícito, escreva um código com comentários próprios e use uma comparação para forçar um booleano.
    {messageCount > 0 && <div>You have messages!</div>}

  • Estou mais à vontade lidando com a falsidade com um ternário -
    {messageCount ? <div>You have messages!</div> : false}

O mesmo acordo no texto datilografado: se você tem uma função que retorna um valor booleano (ou está atribuindo um valor a uma variável booleana), você [geralmente] não pode retornar / atribuir um valor booleano-y; deve ser um booleano fortemente tipado. Isso significa que, se myObjectfor fortemente digitado , return !myObject;funciona para uma função retornando um valor booleano, mas return myObject;não funciona. Você precisa return !!myObjectcorresponder às expectativas do texto datilografado.

A exceção para o Typecript? Se myObjectfoi um any, você está de volta ao Oeste Selvagem do JavaScript e pode devolvê-lo sem !!, mesmo que seu tipo de retorno seja um booleano.

Lembre-se de que essas são convenções JSX e Typescript , não inerentes ao JavaScript .

Mas se você 0vir s estranhos em seu JSX renderizado, pense em um gerenciamento falso falso.


Boa explicação. Então você diria o !! não é estritamente necessário neste exemplo de detecção de recurso Worker ? if (!!window.Worker)
Jk7 6/06/15

2
Não, você não precisaria disso. A verdade e true"externamente" operam exatamente da mesma maneira em um if. Continuo tentando, mas não consigo pensar em um motivo para preferir converter a verdade em um valor booleano fora do tipo complicado de "comparar verdades", acima, exceto pela legibilidade, se você reutilizar o valor posteriormente, como no qexemplo da biblioteca . Mas, mesmo assim, é um atalho com perda de informações e eu diria que é melhor avaliar a veracidade a cada vez.
Ruffin

React é a principal razão pela qual começamos a usar o !! padrão, mas é uma coisa muito conveniente e repetível. Só preciso me preocupar com a veracidade ou falsidade de alguma coisa, e não com o tipo subjacente.

Votos negativos sem comentários dificultam a solução da sua preocupação! Deixe-me saber o que parece ruim e ficarei feliz em resolvê-lo.
Ruffin

55

É apenas o operador lógico NOT, duas vezes - é usado para converter algo em booleano, por exemplo:

true === !!10

false === !!0

3
Por que diabos você faria isso? Use o ! operador para converter em booleano, use === para comparar o tipo? Apenas aceite que você não tem nenhum tipo de segurança e faça val> 0 ou algo assim.
Darren Clark

43
@ Darren: Ele não está comparando tipos; ele está lhe dizendo quais são os resultados, escrevendo afirmações em sua resposta.
Lightness Races in Orbit em


26

É uma notoperação dupla . O primeiro !converte o valor em booleano e inverte seu valor lógico. O segundo !inverte o valor lógico de volta.


26

Parece que o !!operador resulta em dupla negação.

var foo = "Hello World!";

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

23

Simula o comportamento da Boolean()função de fundição. O primeiro NOTretorna um valor booleano, não importa qual operando seja fornecido. O segundo NOTnega esse Booleanvalor e, portanto, fornece o truevalor booleano de uma variável. O resultado final é o mesmo que usar a Boolean()função em um valor.


20

! é "booleano não", que tipifica essencialmente o valor de "enable" para seu oposto booleano. O segundo ! vira esse valor. Portanto, !!enablesignifica "não ativar", fornecendo o valor de enablecomo booleano.


18

Penso que vale a pena mencionar é que uma condição combinada com AND / OR lógico não retornará um valor booleano, mas o último sucesso ou a primeira falha no caso de && e o primeiro sucesso ou a última falha no caso de || da cadeia de condição.

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

Para converter a condição em um literal booleano verdadeiro, podemos usar a dupla negação:

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

17

!!está usando a NOToperação duas vezes juntos, !converta o valor para a booleane inverta-o, aqui está um exemplo simples para ver como !!funciona:

Primeiro, o lugar que você tem:

var zero = 0;

Em seguida !0, ele será convertido em booleano e avaliado como true, porque 0 é falsy, para que você obtenha o valor revertido e convertido em booleano, para que seja avaliado como true.

!zero; //true

mas não queremos a versão booleana invertida do valor, para que possamos revertê-lo novamente para obter nosso resultado! É por isso que usamos outro !.

Basicamente, !!certifique-se de que o valor que obtemos é booleano, não falso, verdadeiro ou string, etc.

Portanto, é como usar a Booleanfunção em javascript, mas de maneira fácil e mais curta para converter um valor em booleano:

var zero = 0;
!!zero; //false

15

A !!construção é uma maneira simples de transformar qualquer expressão JavaScript em seu equivalente booleano.

Por exemplo: !!"he shot me down" === truee !!0 === false.


2
Muito perto da importante distinção. A chave é que 0 === falseé falsa e !!0 === falseverdadeira.
Ruffin

14

Não é um operador único, são dois. É equivalente ao seguinte e é uma maneira rápida de converter um valor em booleano.

val.enabled = !(!enable);

10

Eu suspeito que isso é uma sobra de C ++, onde as pessoas substituem o! operador, mas não o operador bool.

Portanto, para obter uma resposta negativa (ou positiva), nesse caso, você primeiro precisa usar o! operador para obter um booleano, mas se você quisesse verificar o caso positivo usaria !!.


10

O ife whiledeclarações e os ?operadores valores usar a verdade para determinar qual ramo do código seja executado. Por exemplo, os números zero e NaN e a cadeia vazia são falsos, mas outros números e cadeias são verdadeiros. Os objetos são verdadeiros, mas o valor indefinido e nullos dois são falsos.

O operador de dupla negação !!calcula o valor verdadeiro de um valor. Na verdade, são dois operadores, where !!xmean !(!x), e se comportam da seguinte maneira:

  • Se xé um valor falso, !xé truee !!xé false.
  • Se xé um valor verdadeiro, !xé falsee !!xé true.

Quando usado no nível superior de um contexto booleano ( if, while, ou ?), o !!operador é comportamentalmente uma no-op. Por exemplo, if (x)e if (!!x)significa a mesma coisa.

Usos práticos

No entanto, tem vários usos práticos.

Um uso é compactar com perdas um objeto com seu valor de verdade, para que seu código não mantenha uma referência a um objeto grande e o mantenha vivo. Atribuir !!some_big_objecta uma variável em vez de some_big_objectliberá-la para o coletor de lixo. Isso é útil para casos que produzem um objeto ou um valor falso, como nullo valor indefinido, como a detecção de recursos do navegador.

Outro uso, que mencionei em uma resposta sobre o !!operador correspondente de C , é com ferramentas "fiapos" que procuram erros de digitação comuns e diagnósticos de impressão. Por exemplo, em C e JavaScript, alguns erros de digitação comuns para operações booleanas produzem outros comportamentos cuja saída não é tão booleana:

  • if (a = b)é atribuição seguida pelo uso do valor de verdade de b; if (a == b)é uma comparação de igualdade.
  • if (a & b)é um AND bit a bit; if (a && b)é um AND lógico. 2 & 5é 0(um valor falso); 2 && 5é verdade.

O !!operador assegura à ferramenta fiapos que o que você escreveu é o que você quis dizer: faça esta operação e, em seguida, pegue o valor real do resultado.

Um terceiro uso é produzir XOR lógico e XNOR lógico. Em C e JavaScript, a && bexecuta um AND lógico (verdadeiro se ambos os lados forem verdadeiros) e a & bexecuta um AND bit a bit. a || bexecuta um OR lógico (verdadeiro se pelo menos um for verdadeiro) e a | bexecuta um OR bit a bit. Existe um XOR bit a bit (OR exclusivo) como a ^ b, mas não há operador interno para o XOR lógico (verdadeiro se exatamente um lado for verdadeiro). Você pode, por exemplo, permitir que o usuário insira texto em exatamente um dos dois campos. O que você pode fazer é converter cada um para um valor de verdade e compará-los: !!x !== !!y.


8

Negação booleana dupla. Frequentemente usado para verificar se o valor não é indefinido.


8

Toneladas de ótimas respostas aqui, mas se você leu até aqui, isso me ajudou a 'entender'. Abra o console no Chrome (etc) e comece a digitar:

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

Naturalmente, todos são iguais a apenas digitar !! someThing, mas os parênteses adicionados podem ajudar a torná-lo mais compreensível.


8

!!x é uma abreviação de Boolean(x)

O primeiro estrondo força o mecanismo js a funcionar, Boolean(x)mas também tem o efeito colateral de inverter o valor. Então o segundo estrondo desfaz o efeito colateral.


8

Força todas as coisas a serem booleanas.

Por exemplo:

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

Esta pergunta foi respondida completamente, mas eu gostaria de adicionar uma resposta que, espero, seja o mais simplificada possível, criando o significado de !! tão simples de entender quanto possível.

Como o javascript possui o que é chamado de valores "truthy" e "falsey", há expressões que, quando avaliadas em outras expressões, resultam em uma condição verdadeira ou falsa, mesmo que o valor ou expressão que está sendo examinada não seja realmente trueou false.

Por exemplo:

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

Se esse elemento realmente existir, a expressão será avaliada como verdadeira e o bloco de código será executado.

Contudo:

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

... NÃO resultará em uma condição verdadeira e o bloco de código não será executado, mesmo que o elemento exista.

Por quê? Porque document.getElementById()é uma expressão "verdadeira" que será avaliada como verdadeira nesta if()declaração, mas não é um valor booleano real de true.

O duplo "não", neste caso, é bastante simples. São simplesmente dois notsegundos consecutivos.

O primeiro simplesmente "inverte" o valor de verdade ou falsey, resultando em um tipo booleano real e, em seguida, o segundo "inverte" de volta ao seu estado original, mas agora em um valor booleano real. Dessa forma, você tem consistência:

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

e

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

AMBOS retornará verdadeiro, como esperado.


7

Eu só queria adicionar isso

if(variableThing){
  // do something
}

é o mesmo que

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

Mas isso pode ser um problema quando algo não está definido.

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

O truque aqui é que a cadeia de &&s retornará o primeiro valor falsey encontrado - e isso pode ser alimentado com uma instrução if etc. Portanto, se b.foo for indefinido, ele retornará indefinido e ignorará a b.foo.barinstrução, e não obteremos erro.

O retorno acima é indefinido, mas se você tiver uma string vazia, false, null, 0, indefinido, esses valores retornarão e assim que os encontrarmos na cadeia - []e {}ambos forem "verdadeiros" e continuaremos na chamada " && cadeia "para o próximo valor à direita.

PS Outra maneira de fazer a mesma coisa é (b || {}).foo, porque se b for indefinido, b || {}será {}e você acessará um valor em um objeto vazio (sem erro) em vez de tentar acessar um valor dentro de "indefinido" (causa um erro ) Então, (b || {}).fooé o mesmo que b && b.fooe ((b || {}).foo || {}).baré o mesmo que b && b.foo && b.foo.bar.


bom ponto - mudou minha resposta. Isso só acontece em um objeto quando está aninhado em três níveis de profundidade, porque, como você disse, ({}).anythingvai darundefined
Ryan Taylor

5

Depois de ver todas essas ótimas respostas, gostaria de acrescentar outro motivo para o uso !!. Atualmente, estou trabalhando no Angular 2-4 (TypeScript) e quero retornar um booleano como falsequando meu usuário não está autenticado. Se ele não for autenticado, a sequência de token seria nullou "". Eu posso fazer isso usando o próximo bloco de código:

public isAuthenticated(): boolean {
   return !!this.getToken();
}

4

aqui está um pedaço de código de js angular

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

 var rafSupported = !!requestAnimationFrame;

sua intenção é definir rafSupported como true ou false com base na disponibilidade da função em requestAnimationFrame

isso pode ser alcançado verificando da seguinte maneira em geral:

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

o caminho mais curto poderia estar usando !!

rafSupported = !!requestAnimationFrame ;

portanto, se requestAnimationFrame foi designada com uma função, requestAnimationFrame seria false e mais um! disso seria verdade

se requestAnimationFrame foi definido como indefinido, requestAnimationFrame seria verdadeiro e mais um! disso seria falso


3

Alguns operadores em JavaScript realizam conversões implícitas de tipos e, às vezes, são usados ​​para conversão de tipos.

O !operador unário converte seu operando em um booleano e o nega.

Esse fato leva ao seguinte idioma que você pode ver no seu código-fonte:

!!x // Same as Boolean(x). Note double exclamation mark

3

Use o operador lógico não duas vezes,
isso significa! True = false
e !! true = true


3

Retorna o valor booleano de uma variável.

Em vez disso, a Booleanclasse pode ser usada.

(leia as descrições dos códigos)

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`

Ou seja, Boolean(X) = !!Xem uso.

Verifique o trecho de código abaixo

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.