Recientemente leí un código que usa !! para convertir una variable a booleana para evaluación en una declaración if. Esto me parece algo redundante ya que la variable se evaluaría por su valor booleano de todos modos. ¿Hay algún beneficio de rendimiento al hacer esto o es para un mejor soporte del navegador?

Código de muestra:

var x = 0;
var atTop = x===window.scrollY;
if(!!atTop){
   alert("At the top of the page.");
}

Editar :

También he visto esto para operandos que no son de tipo booleano, pero siempre supuse que usar if evaluaría el valor booleano de la variable de todos modos, ya que todos los valores en Javascript son "veraces" o "falsos".

Código de muestra:

var x = 1;//or any other value including null, undefined, some string, etc
if(!!x){//x is "truthy"
   //wouldn't using if(x) be the same???
   console.log("something...");
}
10
Zamboni 8 sep. 2018 a las 01:54

4 respuestas

La mejor respuesta

Respuesta corta : No, no hay razón.

En su código, ya es un tipo boolean, no hay necesidad de convertirlo, y al volver a convertirlo, siempre obtendrá el mismo resultado. En realidad, si tiene algún booleano (true o false), cuando usa !! con cualquiera de ellos, se convertirá de nuevo a su valor inicial:

console.log(!!true); // Will be always "true"
console.log(typeof !!true); // It stills a "boolean" type
console.log(!!false); // Will be always "false"
console.log(typeof !!false); // It stills a "boolean" type

Respuesta para la pregunta editada : Sí, es lo mismo. Eso es lo que hace if(...) en realidad: está tratando de convertir cualquier tipo a boolean.

Aquí hay una pequeña prueba, puedes jugar con eso y agregar lo que quieras dentro de la matriz initialArr para probar, ¿se comporta igual con if y !!:

const initialArr = [
  undefined,
  null,
  true,
  false,
  0,
  3,
  -1,
  +Infinity,
  -Infinity,
  Infinity,
  'any',
  '',
  function() { return 1 },
  {},
  { prop: 1 },
  [],
  [0],
  [0, 1]
];

function testIsTheSame(arr) {
  equolityCounter = 0;
  arr.forEach(item => {
    let ifStatement = false;
    let doubleNotStatement = !!item;
    if(item) {
      ifStatement = true;
    }

    if(ifStatement === doubleNotStatement && typeof ifStatement === typeof doubleNotStatement) {
      equolityCounter++;
    }
  });
  console.log(`Is the same: ${equolityCounter === arr.length}`);
}

testIsTheSame(initialArr);
5
Commercial Suicide 11 sep. 2018 a las 10:06

Todo depende del valor de la variable atTop. Siga la discusión aquí.

En resumen, si el valor de atTop es diferente a boolean, la primera negación lo convertirá en un valor booleano (negado). La segunda negación devolverá el valor booleano al valor booleano equivalente del valor original atTop.

Por ejemplo, si atTop es undefined, primero ! lo convertirá en boolean true, luego el segundo ! lo convertirá en boolean false (que sería el booleano equivalente de undefined)

Sin embargo, en su código el valor atTop es el resultado de una igualdad estricta ===, lo que significa que siempre obtiene un valor booleano como resultado en atTop. Por lo tanto, no necesita convertir un valor no booleano en booleano, por lo que no se necesita !!.

1
Luis Art Guerra 7 sep. 2018 a las 23:15

Yo diría que se hizo principalmente para la legibilidad del código. Dudo que haya implicaciones significativas de rendimiento o compatibilidad (alguien puede probar esto por favor)

Pero en el aspecto de legibilidad de código, implicaría para mí que esta variable anteriormente no era booleana, pero queremos evaluarla como una, si agrega una nueva lógica con respecto a esta variable, tenga esto en cuenta.

Aunque en su caso ya es booleano, es 100% redundante, pero supongo que es solo un hábito de alguien por el razonamiento anterior aplicado en exceso, y / o verlo en otro lugar y copiar ese patrón sin comprenderlo completamente (breve historia: en C # puede nombrar un término protegido como nombre de variable agregando @, por lo que var @class = "hello";, un desarrollador junior asumió todos nombres de variables necesarios @ delante de ellos, y los codifiqué de esa manera. Me pregunto si alguien asumió que un if sin operador de comparación necesita tener !! delante como operador de comparación)

2
Thymine 7 sep. 2018 a las 23:08

No hay ningún beneficio en tiempo de ejecución (o objetivo) en absoluto en hacer esto en una declaración if. La evaluación realizada por la declaración if producirá precisamente el mismo resultado que la evaluación producida por un signo de exclamación doble. No hay diferencia.

Los signos de exclamación dobles son una expresión útil para garantizar un valor booleano basado en la veracidad. Considere, por ejemplo:

var text = undefined;
console.log(text); // undefined
console.log(!!text); // false

// It would make sense here, because a boolean value is expected.
var isTextDefined = !!text;

// It would also affect serialization
JSON.stringify(text); // undefined (non-string)
JSON.stringify(!!text); // "false"

Supongo que este es un hábito que se adoptó debido a los casos de uso anteriores, por lo que siempre se convierte en booleano cuando se desea abordar la veracidad de una variable. Es más fácil para nosotros (humanos y programadores) seguir una regla cuando siempre se aplica. Utilizará las luces intermitentes en su automóvil todo el tiempo, incluso cuando no haya nadie cerca, o es probable que ocasionalmente (o tal vez a menudo) se olvide de indicar cuándo debería haberlo hecho.

1
Ben Barkay 7 sep. 2018 a las 23:28