Pregunta Cuál es el !! (no no) operador en JavaScript?


Vi un código que parece usar un operador que no reconozco, en forma de dos signos de exclamación, así: !!. ¿Puede alguien decirme qué hace este operador?

El contexto en el que vi esto fue

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

2316
2018-04-24 08:13


origen


Respuestas:


Coerces oObject a boolean Si fue falsey (por ejemplo, 0, null, undefined, etc.), será falseDe lo contrario true.

!oObject  //Inverted boolean
!!oObject //Non inverted boolean so true boolean representation

Asi que !! no es un operador, es solo el ! operador dos veces.

Ejemplo del mundo real "Test IE version":

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

Si ⇒

console.log(navigator.userAgent.match(/MSIE 8.0/));  
// returns null  

pero si tu ⇒

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

2068
2018-04-24 08:18



Es una forma horriblemente oscura de hacer una conversión de tipo.

! es NO. Asi que !true es falsey !false es true. !0 es truey !1 es false.

Así que está convirtiendo un valor a booleano, luego invirtiéndolo, y luego invirtiéndolo nuevamente.

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

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

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

729
2017-09-10 17:28



!!expr devuelve un valor booleano (true o false) dependiendo de verdad de la expresión Tiene más sentido cuando se usa en tipos no booleanos. Considere estos ejemplos, especialmente el tercer ejemplo y en adelante:

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

372
2018-05-15 09:06



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 esa false no es true (es por eso !false resultados en true)

  • La verdad es esa true no es false (es por eso !true resultados en false)


!! determina la "verdad" de lo que es un valor no no:

  • La verdad es esa true no es no  true (es por eso !!true resultados en true)

  • La verdad es esa false no es no  false (es por eso !!false resultados en false)


Lo que deseamos determinar en la comparación es la "verdad" acerca de el valor de una referencia, no el valor de la referencia en si misma 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 typeof boolean.


En la práctica:

Considere una función concisa que detecta la funcionalidad de la función (y en este caso, la compatibilidad de la plataforma) por medio de tipeo dinámico (también conocido como "pato escribiendo"). Queremos escribir una función que devuelva true si el navegador de un usuario es compatible con HTML5 <audio> elemento, pero no queremos que la función arroje un error si <audio> es indefinido; y no queremos usar try ... catch para manejar cualquier posible error (porque son burdos); y también no queremos usar un control dentro de la función que no revele la verdad de la función de manera consistente (por ejemplo, document.createElement('audio') seguirá creando un elemento llamado <audio> incluso si HTML5 <audio> no es apoyado).


Aquí están los tres enfoques:

// 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 función acepta un argumento para un <tag> y un attribute buscar, pero cada uno devuelve valores diferentes en función de lo que determinen las comparaciones.

¡Pero espera hay mas!

Algunos de ustedes probablemente han notado que en este ejemplo específico, uno simplemente puede verificar una propiedad usando el más rendimiento medio de verificar si el objeto en cuestión tiene una propiedad. Hay dos maneras de hacer esto:

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

Divagamos ...

Por raras que sean estas situaciones, puede haber algunos escenarios donde los medios más concisos, más efectivos y, por lo tanto, los más preferidos para obtener true desde un valor no booleano, posiblemente indefinido es de hecho mediante el uso de !!. Espero que esto lo aclare ridículamente.


128
2018-02-22 23:45



!! convierte el valor a su derecha a su valor booleano equivalente. (Piensa en la forma en que el hombre pobre usa el "tipo de molde"). Sus intención usualmente es para transmitirle al lector que el código no le importa qué el valor está en la variable, pero lo que es "valor de verdad es.


87
2017-09-10 17:26



!!foo aplica el operador unary not dos veces y se usa para convertir a tipo booleano similar al uso de unario plus +foo lanzar al número y concatenar una cadena vacía ''+foo para lanzar a la cuerda.

En lugar de estos hacks, también puede usar las funciones de constructor correspondientes a los tipos primitivos (sin utilizando new) para emitir valores explícitamente, es decir

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

59
2017-09-10 21:15



Tantas respuestas haciendo la mitad del trabajo. Sí, !!X podría leerse como "la veracidad de X [representado como un booleano]". Pero !! no es, hablando en términos prácticos, tan importante para determinar si una sola variable es (o incluso si son muchas las variables) verdadera o falsa. !!myVar === true es lo mismo que solo myVar. Comparando !!X a un booleano "real" no es realmente útil.

Lo que ganas con !! es la capacidad de verificar la veracidad de múltiples variables unos contra otros en una moda repetible, estandarizada (y amigable con JSLint).

Simplemente lanzando :(

Es decir...

  • 0 === false es false.
  • !!0 === false es true.

Lo anterior no es tan útil. if (!0) te da los mismos resultados que if (!!0 === false). No puedo pensar en un buen caso para convertir una variable a boolean y luego compararla con un booleano "verdadero".

Ver "== y! =" Desde Las indicaciones de JSLint (nota: Crockford está moviendo su sitio un poco, ese enlace es probable que muera en algún momento) por un poco sobre por qué:

Los operadores == y! = Escriben coerción antes de comparar. Esto es malo porque hace que '\ t \ r \ n' == 0 sea verdadero. Esto puede enmascarar errores de tipo. JSLint no puede determinar de manera confiable si == se está utilizando correctamente, por lo que es mejor no usar == y! = En absoluto y usar siempre los operadores más confiables === y !== en su lugar.

Si solo te importa que un valor sea verdadero o falso, entonces usa la forma abreviada. En lugar de
(foo != 0)

sólo decir
(foo)

y en lugar de
(foo == 0)

decir
(!foo)

Tenga en cuenta que hay algunos casos no intuitivos donde un booleano se convertirá en un número (true está lanzado a 1 y false a 0) cuando se compara un booleano con un número. En este caso, !! podría ser mentalmente útil. Aunque, de nuevo, estos son casos en los que se compara un booleano no booleano con un tipo duro, lo que es, un error grave.  if (-1) sigue siendo el camino a seguir aquí.

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

Y las cosas se ponen aún más loca dependiendo de tu motor. WScript, por ejemplo, gana el premio.

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

Porque algunos archivos históricos de Windows, eso arrojará -1 en un cuadro de mensaje! Pruébalo en un mensaje de cmd.exe y ¡mira! Pero WScript.echo(-1 == test()) todavía le da 0 o WScript false. Apartar. Es horrible.

Comparando la verdad :)

Pero, ¿qué pasa si tengo dos valores que necesito verificar para ver el mismo truthi / falsedad?

Pretender que tenemos myVar1 = 0; y myVar2 = undefined;.

  • myVar1 === myVar2 es 0 === undefined y es obviamente falso.
  • !!myVar1 === !!myVar2 es !!0 === !!undefined y es verdad! ¡La misma verdad! (En este caso, ambos "tienen una verdad de falsedad").

Entonces, el único lugar donde realmente necesitarías usar "variables boolean-cast" sería si tuvieras una situación donde estás comprobando si ambas variables tienen el mismo verdad, ¿verdad? Es decir, utilizar !! si necesita ver si dos vars son ambos truthy o ambos falsy (o no), es decir, de igual (o no) verdad.

No puedo pensar en un gran caso de uso no artificioso para eso. ¿Tal vez tiene campos "vinculados" en un formulario?

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

Entonces, si tienes una verdad para ambos o un falso para el nombre del cónyuge y la edad, 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.


EDICION 24 de octubre de 2017: 

Bibliotecas de terceros que esperan valores booleanos explícitos

Aquí hay un caso interesante ... !! podría ser útil cuando libs de terceros esperan valores booleanos explícitos.

Por ejemplo, Falso en JSX (React) tiene un significado especial eso no se desencadena en la falsedad simple. Si ha intentado devolver algo como lo siguiente en su JSX, esperando una int en messageCount...

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

... es posible que se sorprenda al ver que React renderiza 0 cuando tienes cero mensajes Tienes que devolver explícitamente falso para que JSX no represente. La declaración anterior regresa 0, que JSX felizmente renderiza, como debería. No puede decir que no tuviste Count: {messageCount && <div>Get your count to zero!</div>} (o algo menos artificial).

  • Una solución implica el bangbang, que coacciona 0 dentro !!0, cual es false:
    {!!messageCount && <div>You have messages!</div>}

  • Los documentos de JSX sugieren que sea más explícito, escriba código de autocomentarios y use una comparación para forzar a 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}

Manten eso en mente esta es una convención JSX, no uno inherente a JavaScript.

Pero si ves extraño 0s en su JSX prestado, piense en la administración falsa.


45
2018-04-29 18:14



Es simplemente el operador lógico NOT, dos veces: se usa para convertir algo a booleano, por ejemplo:

true === !!10

false === !!0

44
2018-04-24 08:18



Convierte el sufijo en un valor booleano.


28
2017-09-10 17:27