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;
javascript
operators
Teoria do Hexágono
fonte
fonte
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 .Boolean(5/0)
não é o mesmo que!!5/0
!!5/0
produz,Infinity
e nãotrue
como produzido porBoolean(5/0)
.!!5/0
é equivalente a(!!5)/0
- akatrue/0
- devido ao fato de o!
operador ter uma precedência mais alta que o/
operador. Se você deseja fazer um booleano5/0
usando um golpe duplo, precisará usá-lo!!(5/0)
.Respostas:
Converte
Object
paraboolean
. Se fosse Falsey (por exemplo0
,null
,undefined
, etc.), que vai serfalse
, de outra forma,true
.Portanto,
!!
não é um operador, é apenas o!
operador duas vezes.Exemplo do mundo real "Test IE version":
Se você ⇒
Mas se você ⇒
fonte
É uma maneira horrivelmente obscura de fazer uma conversão de tipo.
!
NÃO é . Então!true
éfalse
e!false
étrue
.!0
étrue
e!1
éfalse
.Então você está convertendo um valor para um booleano, invertendo-o e invertendo-o novamente.
fonte
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
!!var
para decodificar emBoolean(var)
.. e!!
é mais rápido (menos instruções para processar) e mais curto que as alternativas.userId != 0
é verdadeiro paranull
,NaN
eundefined
, mas falso parafalse
. 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.!!expr
retorna um valor booleano (true
oufalse
) 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:fonte
!!new Boolean(false) // true
!!Boolean(false) // false
new Boolean(false)
é um objeto e um objeto é verdadeiro, mesmo que contenha um valor falso!String
,Number
,Date
, etc) são destinadas a ser exigível como funções muito, mas, neste caso, o resultado é diferente!new Boolean(false)
retorna umobject
tempoBoolean(false)
retorna o primitivofalse
. Espero que isso faça sentido.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
false
não étrue
(é por isso que!false
resultatrue
)A verdade é que
true
não éfalse
(é por isso que!true
resultafalse
)!!
determina a "verdade" do que não é um valor :A verdade é que
true
não étrue
(é por isso que!!true
resultatrue
)A verdade é que
false
não éfalse
(é por isso que!!false
resultafalse
)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 typeofboolean
.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
true
se 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 usartry ... catch
para 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:
Cada função aceita um argumento para a
<tag>
e anattribute
para 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:
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
true
um valor não booleano e possivelmente indefinido é de fato usando!!
. Espero que isso ridiculamente esclarece.fonte
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 umaif()
instrução. Ou estou perdendo um cenário em que você PRECISA que uma expressão de verdade seja realmente booleanatrue
?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 umaif()
declaração. Por exemploobject.hasTheThing = !!castTheReturnValToBoolNoMatterWhat()
, definiriatrue
ou emfalse
vez do valor de retorno real. Outro exemplo é talvez todos os administradores sãoid
da0
e não-administradores são ID1
ou superior. Paratrue
saber se alguém não é um administrador, você poderia fazerperson.isNotAdmin = !!admin.id
. Poucos casos de uso, mas é conciso quando existe.!!
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" .fonte
!
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.if(0){...
Javascript já sabe que isso é falso. Por que é melhor dizerif(!!0){...
?!!foo
aplica o operador unary not duas vezes e é usado para converter para o tipo booleano semelhante ao uso de unary plus+foo
para converter para número e concatenar uma sequência vazia''+foo
para 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,fonte
new
- como explicitamente mencionado na minha respostax="0"
basta fazer: ox=!!+x; //false
que é o mesmo queBoolean(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!!!+x
vsx !== "0"
?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 apenasmyVar
. 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 queif (!!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:
Observe que existem alguns casos não intuitivos em que um booleano será convertido para um número (
true
é convertido para1
efalse
para0
) 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.E as coisas ficam ainda mais loucas, dependendo do seu motor. O WScript, por exemplo, ganha o prêmio.
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 WScriptfalse
. 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;
emyVar2 = 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?
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 retorna0
, que JSX processa felizmente, como deveria. Não se pode dizer que você não teveCount: {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, masreturn myObject;
não funciona. Você precisareturn !!myObject
corresponder às expectativas do texto datilografado.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.fonte
if (!!window.Worker)
true
"externamente" operam exatamente da mesma maneira em umif
. 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 noq
exemplo da biblioteca . Mas, mesmo assim, é um atalho com perda de informações e eu diria que é melhor avaliar a veracidade a cada vez.É apenas o operador lógico NOT, duas vezes - é usado para converter algo em booleano, por exemplo:
fonte
Ele converte o sufixo em um valor booleano.
fonte
É uma
not
operação dupla . O primeiro!
converte o valor em booleano e inverte seu valor lógico. O segundo!
inverte o valor lógico de volta.fonte
Parece que o
!!
operador resulta em dupla negação.fonte
Simula o comportamento da
Boolean()
função de fundição. O primeiroNOT
retorna um valor booleano, não importa qual operando seja fornecido. O segundoNOT
nega esseBoolean
valor e, portanto, fornece otrue
valor booleano de uma variável. O resultado final é o mesmo que usar aBoolean()
função em um valor.fonte
! é "booleano não", que tipifica essencialmente o valor de "enable" para seu oposto booleano. O segundo ! vira esse valor. Portanto,
!!enable
significa "não ativar", fornecendo o valor deenable
como booleano.fonte
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.
Para converter a condição em um literal booleano verdadeiro, podemos usar a dupla negação:
fonte
!!
está usando aNOT
operação duas vezes juntos,!
converta o valor para aboolean
e inverta-o, aqui está um exemplo simples para ver como!!
funciona:Primeiro, o lugar que você tem:
Em seguida
!0
, ele será convertido em booleano e avaliado comotrue
, porque 0 éfalsy
, para que você obtenha o valor revertido e convertido em booleano, para que seja avaliado comotrue
.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
Boolean
função em javascript, mas de maneira fácil e mais curta para converter um valor em booleano:fonte
A
!!
construção é uma maneira simples de transformar qualquer expressão JavaScript em seu equivalente booleano.Por exemplo:
!!"he shot me down" === true
e!!0 === false
.fonte
0 === false
é falsa e!!0 === false
verdadeira.Não é um operador único, são dois. É equivalente ao seguinte e é uma maneira rápida de converter um valor em booleano.
fonte
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 !!.
fonte
O
if
ewhile
declaraçõ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 enull
os dois são falsos.O operador de dupla negação
!!
calcula o valor verdadeiro de um valor. Na verdade, são dois operadores, where!!x
mean!(!x)
, e se comportam da seguinte maneira:x
é um valor falso,!x
étrue
e!!x
éfalse
.x
é um valor verdadeiro,!x
éfalse
e!!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)
eif (!!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_object
a uma variável em vez desome_big_object
liberá-la para o coletor de lixo. Isso é útil para casos que produzem um objeto ou um valor falso, comonull
o 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 deb
;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 && b
executa um AND lógico (verdadeiro se ambos os lados forem verdadeiros) ea & b
executa um AND bit a bit.a || b
executa um OR lógico (verdadeiro se pelo menos um for verdadeiro) ea | b
executa um OR bit a bit. Existe um XOR bit a bit (OR exclusivo) comoa ^ 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
.fonte
Negação booleana dupla. Frequentemente usado para verificar se o valor não é indefinido.
fonte
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:
Naturalmente, todos são iguais a apenas digitar !! someThing, mas os parênteses adicionados podem ajudar a torná-lo mais compreensível.
fonte
!!x
é uma abreviação deBoolean(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.fonte
Força todas as coisas a serem booleanas.
Por exemplo:
fonte
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
true
oufalse
.Por exemplo:
Se esse elemento realmente existir, a expressão será avaliada como verdadeira e o bloco de código será executado.
Contudo:
... 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 nestaif()
declaração, mas não é um valor booleano real detrue
.O duplo "não", neste caso, é bastante simples. São simplesmente dois
not
segundos 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:
e
AMBOS retornará verdadeiro, como esperado.
fonte
Eu só queria adicionar isso
é o mesmo que
Mas isso pode ser um problema quando algo não está definido.
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á ab.foo.bar
instruçã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 queb && b.foo
e((b || {}).foo || {}).bar
é o mesmo queb && b.foo && b.foo.bar
.fonte
({}).anything
vai darundefined
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 comofalse
quando meu usuário não está autenticado. Se ele não for autenticado, a sequência de token serianull
ou""
. Eu posso fazer isso usando o próximo bloco de código:fonte
aqui está um pedaço de código de js angular
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:
o caminho mais curto poderia estar usando !!
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
fonte
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:
fonte
Use o operador lógico não duas vezes,
isso significa! True = false
e !! true = true
fonte
Retorna o valor booleano de uma variável.
Em vez disso, a
Boolean
classe pode ser usada.(leia as descrições dos códigos)
Ou seja,
Boolean(X) = !!X
em uso.Verifique o trecho de código abaixo ↓
fonte