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/0produce enInfinitylugar detrue, según lo producido porBoolean(5/0).!!5/0es equivalente a(!!5)/0- akatrue/0- debido a que el!operador tiene mayor prioridad que el/operador. Si quisieras Booleanizar5/0usando un doble golpe, deberías usarlo!!(5/0).Respuestas:
Convierte
Objectaboolean. 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í!trueesfalsey!falseestrue.!0estrue, y!1esfalse.Entonces estás convirtiendo un valor en un booleano, luego lo inviertes y luego lo vuelves a invertir.
fuente
userId ? true : falsedeja 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!!varenBoolean(var).. y!!es más rápido (menos instrucciones para procesar) y más cortas que las alternativas.userId != 0es verdadero paranull,NaNyundefined, 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.!!exprdevuelve un valor booleano (trueofalse) 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) // falsenew 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 unobjecttiempoBoolean(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
falseno lo estrue(por eso!falseresultatrue)La verdad es que
trueno lo esfalse(por eso!trueresultafalse)!!determina la "verdad" de lo que un valor no es:La verdad es que
trueno es asítrue(por eso!!trueresultatrue)La verdad es que
falseno es asífalse(por eso!!falseresultafalse)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
truesi 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 ... catchpara 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 anattributepara 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
trueun 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 cualquieratrueo enfalselugar del valor de retorno real. Otro ejemplo es que tal vez todos los administradores sonidde0y los no administradores son id1o superior. Para obtenertruesi 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){...?!!fooaplica el operador no unario dos veces y se utiliza para convertir a tipo booleano similar al uso de unario más+foopara convertir a número y concatenando una cadena vacía''+foopara 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; //falseque 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!!!+xvsx !== "0"?Tantas respuestas haciendo la mitad del trabajo. Sí,
!!Xpodrí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 === truees lo mismo que simplementemyVar. Comparar!!Xun 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 === falseesfalse.!!0 === falseestrue.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 (
truese convierte en1yfalsepara0) 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 === myVar2es0 === undefinedy es obviamente falso.!!myVar1 === !!myVar2es!!0 === !!undefinedy 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
errorObjectscolecció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
0cuando 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
0a!!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
myObjectestá fuertemente tipado ,return !myObject;funciona para una función que devuelve un valor booleano, peroreturn myObject;no lo hace. Tiene quereturn !!myObjectcoincidir con las expectativas de Typecript.Tenga en cuenta que estas son convenciones JSX y mecanografiadas , no inherentes a JavaScript .
Pero si ve
0mensajes 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 elqejemplo 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
notoperació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 primeroNOTdevuelve un valor booleano sin importar qué operando se le dé. El segundoNOTniega eseBooleanvalor y, por lo tanto, da eltruevalor 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,
!!enablesignifica "no habilitar", dándole el valor deenablecomo 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 laNOToperación dos veces juntas,!convierte el valor abooleane 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
Booleanfunció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" === truey!!0 === false.fuente
0 === falsees falsa y!!0 === falsees 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
ifywhilelas 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 ynullambos son falsos.El operador de doble negación
!!calcula el valor de verdad de un valor. En realidad, son dos operadores, donde!!xsignifica!(!x), y se comporta de la siguiente manera:xes un valor falso,!xestruey!!xesfalse.xes un valor verdadero,!xesfalsey!!xestrue.Cuando se utiliza en el nivel superior de un contexto booleano (
if,whileo?), 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_objecta una variable en lugar desome_big_objectsoltarla para el recolector de basura. Esto es útil para casos que producen un objeto o un valor falso comonullo 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 & 5es0(un valor falso);2 && 5es 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 && brealiza un AND lógico (verdadero si ambos lados son verdaderos) ya & brealiza un AND bit a bit.a || brealiza un OR lógico (verdadero si al menos uno es verdadero) ya | brealiza 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
!!xes 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
trueofalse.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
notsegundos 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.bardeclaració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 || {}).fooes lo mismob && b.fooy((b || {}).foo || {}).bares lo mismo queb && b.foo && b.foo.bar.fuente
({}).anything, cederáundefinedDespué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 comofalsecuando mi usuario no está autenticado. Si no está autenticado, el token-string seríanullo"". 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,
Booleanse puede usar la clase.(lea las descripciones de los códigos)
A saber,
Boolean(X) = !!Xen uso.Verifique el fragmento de código a continuación ↓
fuente