Tantas respostas fazendo metade do trabalho. Sim, !!X
poderia 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 !!X
com 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 1
e false
para 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 === undefined
e é obviamente falso.
!!myVar1 === !!myVar2
é !!0 === !!undefined
e é 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 errorObjects
coleçã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 0
quando 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 0
em !!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 myObject
for fortemente digitado , return !myObject;
funciona para uma função retornando um valor booleano, mas return myObject;
não funciona. Você precisa return !!myObject
corresponder às expectativas do texto datilografado.
A exceção para o Typecript? Se myObject
foi 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ê 0
vir s estranhos em seu JSX renderizado, pense em um gerenciamento falso falso.