Vi un código que parece utilizar un operador que no reconozco, en forma de dos signos de exclamación, así: !!
. ¿Alguien puede decirme qué hace este operador?
El contexto en el que vi esto fue,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
javascript
operators
Teoría del hexágono
fuente
fuente
if(vertical !== undefined) this.vertical = Boolean(vertical);
: es mucho más claro y claro lo que está sucediendo, no requiere una asignación innecesaria, es completamente estándar y es igual de rápido (en FF y Chrome actuales ) jsperf.com/boolean-conversion-speed .Boolean(5/0)
no es lo mismo que!!5/0
!!5/0
produce enInfinity
lugar detrue
, según lo producido porBoolean(5/0)
.!!5/0
es equivalente a(!!5)/0
- akatrue/0
- debido a que el!
operador tiene mayor prioridad que el/
operador. Si quisieras Booleanizar5/0
usando un doble golpe, deberías usarlo!!(5/0)
.Respuestas:
Convierte
Object
aboolean
. Si era Falsey (por ejemplo0
,null
,undefined
, etc.), seráfalse
, de lo contrario,true
.Entonces
!!
no es un operador, es solo el!
operador dos veces.Ejemplo del mundo real "Versión de prueba de IE":
Si ⇒
Pero si ⇒
fuente
Es una forma horriblemente oscura de hacer una conversión de tipo.
!
es NO . Así!true
esfalse
y!false
estrue
.!0
estrue
, y!1
esfalse
.Entonces estás convirtiendo un valor en un booleano, luego lo inviertes y luego lo vuelves a invertir.
fuente
userId ? true : false
deja más claro que hay una conversión en curso y maneja el caso en el que el valor de userId podría haberse establecido explícitamente enundefined
!!var
enBoolean(var)
.. y!!
es más rápido (menos instrucciones para procesar) y más cortas que las alternativas.userId != 0
es verdadero paranull
,NaN
yundefined
, pero falso parafalse
. Si desea exactamente ese comportamiento, probablemente debería ser explícito al respecto. Pero incluso si funcionó exactamente igual!!userId
, no está claro si desea que esos valores salgan falsos aquí, o si simplemente no tuvo en cuenta las reglas de conversión de tipos de Javascript.!!expr
devuelve un valor booleano (true
ofalse
) según la veracidad de la expresión. Tiene más sentido cuando se usa en tipos no booleanos. Considere estos ejemplos, especialmente el 3er ejemplo y en adelante:fuente
!!new Boolean(false) // true
!!Boolean(false) // false
new Boolean(false)
es un objeto y un objeto es verdadero incluso si contiene un valor falso.String
,Number
,Date
, etc.) están destinados a ser exigible como funciones también, sin embargo, en este caso el resultado es diferente!new Boolean(false)
devuelve unobject
tiempoBoolean(false)
devuelve lo primitivofalse
. Espero que esto tenga sentido.Prepara un poco de té:
!!
No es un operador. Es el doble uso de!
, que es el operador lógico "no".En teoria:
!
determina la "verdad" de lo que no es un valor:La verdad es que
false
no lo estrue
(por eso!false
resultatrue
)La verdad es que
true
no lo esfalse
(por eso!true
resultafalse
)!!
determina la "verdad" de lo que un valor no es:La verdad es que
true
no es asítrue
(por eso!!true
resultatrue
)La verdad es que
false
no es asífalse
(por eso!!false
resultafalse
)Lo que deseamos determinar en la comparación es la "verdad" sobre el valor de una referencia, no el valor de la referencia en sí. Hay un caso de uso en el que podríamos querer saber la verdad sobre un valor, incluso si esperamos que el valor sea
false
(o falsey), o si esperamos que el valor no sea typeofboolean
.En la práctica:
Considere una función concisa que detecta la funcionalidad de la característica (y en este caso, la compatibilidad de la plataforma) a través de la escritura dinámica (también conocida como "escritura de pato"). Queremos escribir una función que regrese
true
si el navegador de un usuario admite el<audio>
elemento HTML5 , pero no queremos que la función arroje un error si<audio>
no está definida; y no queremos usartry ... catch
para manejar posibles errores (porque son asquerosos); y tampoco queremos usar una verificación dentro de la función que no revelará constantemente la verdad sobre la función (por ejemplo,document.createElement('audio')
seguirá creando un elemento llamado<audio>
incluso si HTML5<audio>
no es compatible).Aquí están los tres enfoques:
Cada función acepta un argumento para a
<tag>
y anattribute
para buscar, pero cada uno devuelve valores diferentes en función de lo que determinan las comparaciones.¡Pero espera hay mas!
Algunos de ustedes probablemente notaron que en este ejemplo específico, uno simplemente podría verificar una propiedad utilizando los medios ligeramente más eficaces para verificar si el objeto en cuestión tiene una propiedad. Hay dos maneras de hacer esto:
Estamos divagando ...
Por muy raras que puedan ser estas situaciones, puede haber algunos escenarios en los que el medio más conciso, más eficaz y, por lo tanto, el más preferido para obtener
true
un valor no booleano, posiblemente indefinido, es el uso!!
. Esperemos que esto lo aclare ridículamente.fuente
if()
declaración ya convierte la expresión en booleana, la conversión explícita del valor de retorno de una función de prueba a booleana es redundante, ya que "veracidad" === verdadero hasta dondeif()
llega una declaración de todos modos. ¿O me estoy perdiendo un escenario en el que NECESITAS que una expresión de verdad sea realmente booleanatrue
?if()
declaraciones de @TomAuger emiten valores booleanos contra valores de falsey, pero dicen que realmente desea establecer una bandera booleana en un objeto; no lo emitirá como lo hace unaif()
declaración. Por ejemploobject.hasTheThing = !!castTheReturnValToBoolNoMatterWhat()
, establecería cualquieratrue
o enfalse
lugar del valor de retorno real. Otro ejemplo es que tal vez todos los administradores sonid
de0
y los no administradores son id1
o superior. Para obtenertrue
si alguien no es un administrador que podría hacerperson.isNotAdmin = !!admin.id
. Pocos casos de uso, pero es conciso cuando lo hay.!!
convierte el valor a su derecha en su valor booleano equivalente. (Piense en la forma de "fundición de tipos" del pobre). Por lo general, su intención es transmitir al lector que al código no le importa qué valor tiene la variable, sino cuál es su valor de "verdad" .fuente
!
todavía voltea el valor a la derecha. En el caso de un booleano, el extremo derecho!
niega el valor, mientras que el!
extremo izquierdo lo niega una vez más. El efecto neto es que no hay cambios, pero la mayoría de los motores generarán códigos operativos para la doble negación.if(0){...
Javascript ya sabe que esto es falso. ¿Por qué es mejor decirloif(!!0){...
?!!foo
aplica el operador no unario dos veces y se utiliza para convertir a tipo booleano similar al uso de unario más+foo
para convertir a número y concatenando una cadena vacía''+foo
para convertir a cadena.En lugar de estos hacks, también puede usar las funciones de constructor correspondientes a los tipos primitivos ( sin usar
new
) para emitir valores explícitamente, es decirfuente
new
, como se menciona explícitamente en mi respuestax="0"
simplemente hacer:x=!!+x; //false
que es lo mismo queBoolean(Number(x))
Número (o + x) convierte la cadena "0" a 0, que SÍ evalúa a falso, y luego Booleano (!! x) lo convierte en booleano directamente. ¡Pan comido!!!+x
vsx !== "0"
?Tantas respuestas haciendo la mitad del trabajo. Sí,
!!X
podría leerse como "la veracidad de X [representada como booleana]". Pero!!
, en términos prácticos, no es tan importante para determinar si una sola variable es (o incluso si muchas variables son) verdadera o falsa.!!myVar === true
es lo mismo que simplementemyVar
. Comparar!!X
un booleano "real" no es realmente útil.Con lo que se gana
!!
es con la capacidad de verificar la veracidad de múltiples variables entre sí de manera repetible, estandarizada (y amigable con JSLint).Simplemente casting :(
Es decir...
0 === false
esfalse
.!!0 === false
estrue
.Lo anterior no es tan útil.
if (!0)
te da los mismos resultados queif (!!0 === false)
. No puedo pensar en un buen caso para convertir una variable en booleana y luego compararla con una booleana "verdadera".Vea "== y! =" En las instrucciones de JSLint (nota: Crockford está moviendo su sitio un poco; ese enlace puede morir en algún momento) por un poco sobre por qué:
Tenga en cuenta que hay algunos casos poco intuitivos en los que un booleano se convertirá en un número (
true
se convierte en1
yfalse
para0
) al comparar un booleano con un número. En este caso,!!
podría ser mentalmente útil. Sin embargo, de nuevo, estos son casos en los que se compara un booleano no booleano con un booleano de tipo rígido, lo cual es un error grave.if (-1)
sigue siendo el camino a seguir aquí.Y las cosas se ponen aún más locas dependiendo de tu motor. WScript, por ejemplo, gana el premio.
¡Debido a algunos cambios históricos de Windows , eso generará -1 en un cuadro de mensaje! ¡Pruébelo en un indicador de cmd.exe y vea! Pero
WScript.echo(-1 == test())
aún así te da 0, o WScriptfalse
. Apartar. Es horribleComparando la veracidad :)
Pero, ¿qué pasa si tengo dos valores que necesito verificar para verdades / falsidades iguales?
Finge que tenemos
myVar1 = 0;
ymyVar2 = undefined;
.myVar1 === myVar2
es0 === undefined
y es obviamente falso.!!myVar1 === !!myVar2
es!!0 === !!undefined
y es verdad! La misma veracidad! (En este caso, ambos "tienen una verdad de falsedad").Entonces, el único lugar en el que realmente necesitaría usar "variables de conversión booleana" sería si tuviera una situación en la que esté verificando si ambas variables tienen la misma veracidad, ¿verdad? Es decir, el uso
!!
si es necesario para ver si son dos vars tanto Truthy o ambos Falsy (o no), es decir, de igual (o no) truthiness .No puedo pensar en un gran caso de uso no ideado para esa mano abierta. ¿Quizás tiene campos "vinculados" en un formulario?
Entonces, si tiene una verdad para ambos o una falsa para el nombre y la edad del cónyuge, puede continuar. De lo contrario, solo tiene un campo con un valor (o un matrimonio arreglado muy temprano) y necesita crear un error adicional en su
errorObjects
colección.EDITAR 24 oct 2017, 6 feb 19:
Bibliotecas de terceros que esperan valores booleanos explícitos
Aquí hay un caso interesante ...
!!
podría ser útil cuando las bibliotecas de terceros esperan valores booleanos explícitos.Por ejemplo, False en JSX (React) tiene un significado especial que no se desencadena en la falsedad simple. Si intentó devolver algo como lo siguiente en su JSX, esperando un int en
messageCount
...{messageCount && <div>You have messages!</div>}
... es posible que se sorprenda al ver que React se procesa
0
cuando tiene cero mensajes. Debe devolver explícitamente false para que JSX no se procese. La declaración anterior regresa0
, que JSX representa felizmente, como debería. No se puede decir que no teníaCount: {messageCount && <div>Get your count to zero!</div>}
(o algo menos artificial).Una solución consiste en la bangbang, que coacciona
0
a!!0
, que esfalse
:{!!messageCount && <div>You have messages!</div>}
Los documentos de JSX sugieren que seas más explícito, que escribas un código de auto comentario y que uses una comparación para forzar un booleano.
{messageCount > 0 && <div>You have messages!</div>}
Me siento más cómodo manejando la falsedad con un ternario.
{messageCount ? <div>You have messages!</div> : false}
Mismo trato en Typecript: si tiene una función que devuelve un valor booleano (o está asignando un valor a una variable booleana), [generalmente] no puede devolver / asignar un valor booleano-y; Tiene que ser un booleano fuertemente tipado. Esto significa que si iff
myObject
está fuertemente tipado ,return !myObject;
funciona para una función que devuelve un valor booleano, peroreturn myObject;
no lo hace. Tiene quereturn !!myObject
coincidir con las expectativas de Typecript.Tenga en cuenta que estas son convenciones JSX y mecanografiadas , no inherentes a JavaScript .
Pero si ve
0
mensajes extraños en su JSX renderizado, piense en una gestión falsa.fuente
if (!!window.Worker)
true
"externamente" operan exactamente igual en unif
. Sigo intentándolo, pero no puedo pensar en una razón para preferir convertir la veracidad en un valor booleano fuera del tipo de caso complicado de "comparar verdades", arriba, excepto por la legibilidad si reutiliza el valor más tarde, como en elq
ejemplo de la biblioteca . Pero incluso entonces, es un acceso directo con pérdida de información, y diría que es mejor que evalúe la veracidad cada vez.Es solo el operador lógico NOT, dos veces: se usa para convertir algo a booleano, por ejemplo:
fuente
Convierte el sufijo en un valor booleano.
fuente
Es una doble
not
operación. El primero!
convierte el valor a booleano e invierte su valor lógico. El segundo!
invierte el valor lógico de nuevo.fuente
Parece que el
!!
operador resulta en una doble negación.fuente
Simula el comportamiento de la
Boolean()
función de fundición. El primeroNOT
devuelve un valor booleano sin importar qué operando se le dé. El segundoNOT
niega eseBoolean
valor y, por lo tanto, da eltrue
valor booleano de una variable. El resultado final es el mismo que usar laBoolean()
función en un valor.fuente
! es "no booleano", que esencialmente encasilla el valor de "habilitar" a su opuesto booleano. El segundo ! Voltea este valor. Entonces,
!!enable
significa "no habilitar", dándole el valor deenable
como un booleano.fuente
Creo que vale la pena mencionar que una condición combinada con AND / OR lógico no devolverá un valor booleano, sino el último éxito o el primer error en el caso de && y el primer éxito o el último error en el caso de || de condición de cadena.
Para convertir la condición a un verdadero literal booleano, podemos usar la doble negación:
fuente
!!
usa laNOT
operación dos veces juntas,!
convierte el valor aboolean
e inviertelo, aquí hay un ejemplo simple para ver cómo!!
funcionaAl principio, el lugar que tienes:
Luego
!0
, se convertirá a booleano y se evaluará atrue
, porque 0 esfalsy
, por lo que obtiene el valor invertido y se convierte a booleano, por lo que se evalúa atrue
.pero no queremos la versión booleana invertida del valor, por lo que podemos invertirla nuevamente para obtener nuestro resultado. Por eso usamos otro
!
.Básicamente,
!!
asegúrate de que el valor que obtenemos es booleano, no falso, verdadero o cadena, etc.Entonces, es como usar la
Boolean
función en javascript, pero es una forma fácil y más corta de convertir un valor a booleano:fuente
La
!!
construcción es una forma simple de convertir cualquier expresión de JavaScript en su equivalente booleano.Por ejemplo:
!!"he shot me down" === true
y!!0 === false
.fuente
0 === false
es falsa y!!0 === false
es verdadera.No es un solo operador, son dos. Es equivalente a lo siguiente y es una forma rápida de convertir un valor en booleano.
fuente
Sospecho que esto es un sobrante de C ++ donde la gente anula el! operador pero no el operador bool.
Por lo tanto, para obtener una respuesta negativa (o positiva) en ese caso, primero debe usar! operador para obtener un booleano, pero si quisieras marcar el caso positivo lo usarías !!.
fuente
El
if
ywhile
las declaraciones y los?
valores de uso de la verdad operador determinar qué rama de la ejecución de código. Por ejemplo, los números cero y NaN y la cadena vacía son falsos, pero otros números y cadenas son verdaderos. Los objetos son verdaderos, pero el valor indefinido ynull
ambos son falsos.El operador de doble negación
!!
calcula el valor de verdad de un valor. En realidad, son dos operadores, donde!!x
significa!(!x)
, y se comporta de la siguiente manera:x
es un valor falso,!x
estrue
y!!x
esfalse
.x
es un valor verdadero,!x
esfalse
y!!x
estrue
.Cuando se utiliza en el nivel superior de un contexto booleano (
if
,while
o?
), el!!
operador es conductualmente un no-op. Por ejemplo,if (x)
yif (!!x)
significa lo mismo.Usos prácticos
Sin embargo, tiene varios usos prácticos.
Un uso es comprimir con pérdida un objeto a su valor de verdad, para que su código no tenga una referencia a un objeto grande y lo mantenga vivo. Asignación
!!some_big_object
a una variable en lugar desome_big_object
soltarla para el recolector de basura. Esto es útil para casos que producen un objeto o un valor falso comonull
o el valor indefinido, como la detección de características del navegador.Otro uso, que mencioné en una respuesta sobre el
!!
operador correspondiente de C , es con herramientas de "pelusa" que buscan errores tipográficos comunes y diagnósticos de impresión. Por ejemplo, tanto en C como en JavaScript, algunos errores tipográficos comunes para las operaciones booleanas producen otros comportamientos cuya salida no es tan booleana:if (a = b)
es la asignación seguida del uso del valor de verdad deb
;if (a == b)
Es una comparación de igualdad.if (a & b)
es un bit a bit Y;if (a && b)
es un AND lógico.2 & 5
es0
(un valor falso);2 && 5
es verdad.El
!!
operador asegura a la herramienta de pelusa que lo que escribió es lo que quiso decir: realice esta operación, luego tome el valor verdadero del resultado.Un tercer uso es producir XOR lógico y XNOR lógico. Tanto en C como en JavaScript,
a && b
realiza un AND lógico (verdadero si ambos lados son verdaderos) ya & b
realiza un AND bit a bit.a || b
realiza un OR lógico (verdadero si al menos uno es verdadero) ya | b
realiza un OR bit a bit. Hay un XOR bit a bit (OR exclusivo) comoa ^ b
, pero no hay un operador incorporado para XOR lógico (verdadero si exactamente un lado es verdadero). Es posible que, por ejemplo, desee permitir que el usuario ingrese texto en exactamente uno de los dos campos. Lo que puede hacer es convertir cada uno a un valor de verdad y ellos se compara:!!x !== !!y
.fuente
Doble negación booleana. A menudo se usa para verificar si el valor no está indefinido.
fuente
Toneladas de excelentes respuestas aquí, pero si has leído hasta aquí, esto me ayudó a 'entenderlo'. Abra la consola en Chrome (etc.) y comience a escribir:
Naturalmente, todo esto es lo mismo que simplemente escribir algo, pero los paréntesis adicionales pueden ayudar a que sea más comprensible.
fuente
!!x
es taquigrafía paraBoolean(x)
La primera explosión fuerza al motor js a funcionar,
Boolean(x)
pero también tiene el efecto secundario de invertir el valor. Entonces, la segunda explosión deshace el efecto secundario.fuente
Obliga a todas las cosas a ser booleanas.
Por ejemplo:
fuente
Esta pregunta ha sido respondida a fondo, pero me gustaría agregar una respuesta que espero sea lo más simplificada posible, ¡lo que significa! tan simple de entender como puede ser.
Debido a que javascript tiene lo que se llama valores "veraces" y "falsey", existen expresiones que, cuando se evalúan en otras expresiones, darán como resultado una condición verdadera o falsa, aunque el valor o la expresión que se está examinando no sea realmente
true
ofalse
.Por ejemplo:
Si ese elemento existe, la expresión se evaluará como verdadera y se ejecutará el bloque de código.
Sin embargo:
... NO dará como resultado una condición verdadera, y el bloque de código no se ejecutará, incluso si el elemento existe.
¿Por qué? Porque
document.getElementById()
es una expresión "veraz" que se evaluará como verdadera en estaif()
declaración, pero no es un valor booleano real detrue
.El doble "no" en este caso es bastante simple. Es simplemente dos
not
segundos seguidos.El primero simplemente "invierte" el valor verdadero o falso, dando como resultado un tipo booleano real, y luego el segundo "lo invierte" nuevamente a su estado original, pero ahora en un valor booleano real. De esa manera tienes consistencia:
y
AMBOS devolverá verdadero, como se esperaba.
fuente
Solo quería agregar eso
es lo mismo que
Pero esto puede ser un problema cuando algo no está definido.
El truco aquí es que la cadena de
&&
s devolverá el primer valor de falsey que encuentre, y esto se puede alimentar a una declaración if, etc. Así que si b.foo no está definido, volverá indefinido y omitirá lab.foo.bar
declaración, y no obtendremos error.Los valores anteriores devuelven indefinidos, pero si tiene una cadena vacía, falsa, nula, 0, indefinida, esos valores regresarán y tan pronto como los encontremos en la cadena,
[]
y{}
ambos sean "verdaderos" y continuaremos por el llamado " && encadena "al siguiente valor a la derecha.PD Otra forma de hacer lo mismo es
(b || {}).foo
, porque si b está indefinido, entoncesb || {}
lo estará{}
, y accederá a un valor en un objeto vacío (sin error) en lugar de intentar acceder a un valor dentro de "indefinido" (provoca un error ) Entonces,(b || {}).foo
es lo mismob && b.foo
y((b || {}).foo || {}).bar
es lo mismo queb && b.foo && b.foo.bar
.fuente
({}).anything
, cederáundefined
Después de ver todas estas excelentes respuestas, me gustaría agregar otra razón para usar
!!
. Actualmente estoy trabajando en Angular 2-4 (TypeScript) y quiero devolver un booleano comofalse
cuando mi usuario no está autenticado. Si no está autenticado, el token-string seríanull
o""
. Puedo hacer esto usando el siguiente bloque de código:fuente
aquí hay un fragmento de código de angular js
su intención es establecer rafSupported en verdadero o falso según la disponibilidad de la función en requestAnimationFrame
Se puede lograr comprobando de la siguiente manera en general:
el camino corto podría estar usando !!
así que si requestAnimationFrame se le asignó una función, ¡requestAnimationFrame sería falso y uno más! de eso sería cierto
si requestAnimationFrame fue asignado indefinido, ¡requestAnimationFrame sería verdadero y uno más! de eso sería falso
fuente
Algunos operadores en JavaScript realizan conversiones de tipo implícitas y, a veces, se utilizan para la conversión de tipo.
El
!
operador unario convierte su operando a un booleano y lo niega.Este hecho lleva al siguiente modismo que puedes ver en tu código fuente:
fuente
Use el operador lógico no dos veces
, significa! Verdadero = falso
y !! verdadero = verdadero
fuente
Devuelve el valor booleano de una variable.
En cambio,
Boolean
se puede usar la clase.(lea las descripciones de los códigos)
A saber,
Boolean(X) = !!X
en uso.Verifique el fragmento de código a continuación ↓
fuente