web-dev-qa-db-fra.com

Pourquoi utiliser des points d'exclamation doubles dans une instruction if?

J'ai récemment lu du code qui utilise !! pour convertir une variable en booléen à des fins d'évaluation dans une instruction if. Cela me semble quelque peu redondant car la variable serait de toute façon évaluée pour sa valeur booléenne. Existe-t-il des avantages en termes de performances ou s’agit-il d’une meilleure prise en charge du navigateur?

Exemple de code:

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

Modifier :

J'ai également vu cela pour des opérandes qui ne sont pas de types booléens, mais j'avais toujours supposé que l'utilisation de if évaluerait de toute façon la valeur booléenne de la variable car toutes les valeurs en Javascript sont soit "vérité" soit "falsey".

Exemple de code:

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...");
}
9
Zamboni

Réponse courte : Non, il n'y a pas de raison.

Dans votre code, il s'agit déjà d'un type boolean, il n'est pas nécessaire de le convertir et de le reconvertir, vous obtiendrez toujours le même résultat. En fait, si vous avez un booléen (true ou false), lorsque vous utilisez !! avec l’un d’eux, il sera reconverti à sa valeur initiale:

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

Réponse pour la question modifiée : Oui, c'est pareil. C'est ce que if(...) fait réellement - il essaye de convertir n'importe quel type en boolean.

Voici un petit test, vous pouvez jouer avec cela et ajouter ce que vous voulez dans le tableau initialArr à tester, est-ce que cela se comporte de la même manière avec if et !!

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

Je dirais que cela a principalement été fait pour la lisibilité du code. Je doute qu'il y ait des conséquences importantes sur les performances et la compatibilité (quelqu'un se sent libre de le tester, s'il vous plaît)

Mais en ce qui concerne l'aspect lisibilité du code, cela impliquerait pour moi que cette variable n'était auparavant pas un booléen, mais nous voulons l'évaluer comme telle, si vous ajoutez une nouvelle logique concernant cette variable, gardez cela à l'esprit.

Bien que, dans votre cas, il soit déjà booléen, il est donc redondant à 100%, mais j’imagine que le raisonnement ci-dessus est une habitude de l’appliquer de manière excessive et/ou le voir ailleurs et le copier sans le comprendre parfaitement en C #, vous pouvez nommer un nom de variable en ajoutant @, donc var @class = "hello";, un développeur junior vient d'assumer all noms de variables nécessaires @ devant eux, et codé de cette façon. Je me demande si quelqu'un a supposé que si sans opérateur de comparaison, il doit précéder !! en tant qu'opérateur de comparaison)

2
Thymine

Il n'y a aucun avantage d'exécution (ou objectif) à le faire dans une instruction if. L'évaluation effectuée par la déclaration if donnera exactement le même résultat que l'évaluation produite par le point d'exclamation double. Il n'y a pas de différence.

Les doubles points d'exclamation sont une expression utile pour garantir une valeur booléenne basée sur la vérité. Considérons, par exemple:

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"

Je suppose que c'est une habitude qui a été adoptée à cause des cas d'utilisation ci-dessus, convertissant ainsi toujours en booléen lorsque vous souhaitez aborder la véracité d'une variable. Il est plus facile pour nous (humains et programmeurs) de suivre une règle quand elle est toujours appliquée. Vous utiliserez les clignotants dans votre voiture tout le temps, même s'il n'y a personne, ou il est probable que vous oublierez de temps en temps (ou souvent) de signaler quand vous devriez le faire.

1
Ben Barkay

Tout dépend de la valeur de la variable atTop. Suivez la discussion ici .

En résumé, si la valeur de atTop est différente de celle de boolean, la première négation la convertira en une valeur booléenne (annulée). La deuxième négation renverra la valeur booléenne à la valeur booléenne équivalente à la valeur atTop originale.

Par exemple, si atTop est undefined, le premier ! le transformera en boolean true, puis le second ! le transformera en boolean false (ce qui serait le booléen équivalent de undefined

Cependant, dans votre code, la valeur atTop est le résultat d'une égalité stricte ===, ce qui signifie que vous obtenez toujours un booléen résultant dans atTop. Ainsi, vous n'avez pas besoin de convertir une valeur non booléenne en valeur booléenne. Le !! n'est donc pas nécessaire.

1
Luis Art Guerra