web-dev-qa-db-fra.com

Quel est le !! (pas pas) opérateur en JavaScript?

J'ai vu un code qui semble utiliser un opérateur que je ne reconnais pas, sous la forme de deux points d'exclamation, comme suit: !!. Quelqu'un peut-il me dire ce que cet opérateur fait?

Le contexte dans lequel j'ai vu cela était,

this.vertical = vertical !== undefined ? !!vertical : this.vertical;
2605
Hexagon Theory

Coûte oObject à booléen. S'il s'agissait de falsey (par exemple 0, null, undefined, etc.), il s'agira de false, sinon true.

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

Donc, !! n'est pas un opérateur, c'est simplement l'opérateur ! à deux reprises.

Exemple du monde réel "Version de test IE": 

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

Si vous ⇒

console.log(navigator.userAgent.match(/MSIE 8.0/));  
// returns either an Array or null  

mais si vous ⇒

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

C'est une façon horriblement obscure de faire une conversion de type.

! estPAS. Donc, !true est false et !false est true. !0 est true et !1 est false.

Donc, vous convertissez une valeur en un booléen, puis vous l'inversez, puis vous l'inversez à nouveau.

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

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

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

!!expr renvoie une valeur booléenne (true ou false) en fonction de la vérité de l'expression. Cela a plus de sens lorsqu'il est utilisé sur des types non booléens. Considérez ces exemples, en particulier le 3ème exemple et les suivants:

          !!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!
410
Salman A

Préparez du thé:

!! n'est pas un opérateur. C'est la double utilisation de ! - qui est l'opérateur logique "pas". 


En théorie:

! détermine la "vérité" de ce qu'une valeur n'est pas:

  • La vérité est que false n'est pas true (c'est pourquoi !false résultatsin true)

  • La vérité est que true n'est pas false (c'est pourquoi !true résultatsin false)


!! détermine la "vérité" de ce qu'une valeur est not not:

  • La vérité est que true n'est pas pastrue (c'est pourquoi !!true a pour résultat true)

  • La vérité est que false n'est pas pasfalse (c'est pourquoi !!false a pour résultat false)


Ce que nous souhaitons déterminer dans la comparaison est la "vérité" environ la valeur d'une référence, pas le valeur de la référence elle-même. Il existe un cas d'utilisation où nous pourrions vouloir connaître la vérité sur une valeur, même si nous nous attendons à ce que la valeur soit false (ou falsey), ou si nous nous attendons à ce que la valeur ne soit pas typeof boolean


En pratique:

Considérez une fonction concise qui détecte la fonctionnalité des fonctionnalités (et dans ce cas, la compatibilité de la plate-forme) au moyen de typage dynamique (ou "typage de canard"). Nous voulons écrire une fonction qui retourne true si le navigateur d'un utilisateur prend en charge l'élément HTML5 <audio>, mais nous ne voulons pas que la fonction génère une erreur si <audio> est indéfini; et nous ne voulons pas utiliser try ... catch pour traiter les erreurs éventuelles (car elles sont grossières); et aussi nous ne voulons pas utiliser de contrôle dans la fonction qui ne révélera pas systématiquement la vérité sur la fonctionnalité (par exemple, document.createElement('audio') créera toujours un élément appelé <audio> même si HTML5 <audio> n'est pas pris en charge. ). 


Voici les trois approches:

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

Chaque fonction accepte un argument pour <tag> et une attribute à rechercher, mais chacune renvoie des valeurs différentes en fonction de ce que les comparaisons déterminent. 

Mais attendez, il y a plus!

Certains d'entre vous ont probablement remarqué que dans cet exemple spécifique, on pourrait simplement vérifier une propriété en utilisant le moyen légèrement plus performant de vérifier si l'objet en question a une propriété. Il y a deux façons de faire ça:

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

Nous nous éloignons ...

Si rares que soient ces situations, il peut exister quelques scénarios dans lesquels le moyen le plus concis, le plus performant et, par conséquent, le plus privilégié d’obtenir true à partir d’une valeur non booléenne, éventuellement indéfinie, est bien en utilisant !!. Espérons que cela éclaircit ridiculement.

140
Benny

!! convertit la valeur située à droite de celle-ci en sa valeur booléenne équivalente. (Pensez à la manière du pauvre homme de "faire le typage"). Son intention est généralement de faire comprendre au lecteur que le code ne s’intéresse pas à la valeur de dans la variable, mais à sa "vérité" valeur est.

91
Crescent Fresh

!!foo applique l'opérateur unary not deux fois et est utilisé pour transtyper en type booléen de la même manière que l'utilisation de unary plus +foo pour transtyper en nombre et concaténer une chaîne vide ''+foo en transtyper en chaîne.

Au lieu de ces hacks, vous pouvez également utiliser les fonctions de constructeur correspondant aux types primitifs ( sans en utilisant new) pour explicitement convertir des valeurs, c'est-à-dire

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

C'est juste l'opérateur logique NOT, deux fois - il est utilisé pour convertir quelque chose en booléen, par exemple:

true === !!10

false === !!0
50
Greg

Il convertit le suffixe en une valeur booléenne. 

30
Paul McMillan

C'est une double opération not. Le premier ! convertit la valeur en booléen et inverse sa valeur logique. Le second ! inverse la valeur logique.

24
Bill the Lizard

Il simule le comportement de la fonction de transtypage Boolean() . La première NOT renvoie une valeur booléenne, quel que soit l'opérande qui lui est attribué. La seconde NOT annule cette valeur Boolean et donne donc la valeur true Boolean d'une variable. Le résultat final est identique à l'utilisation de la fonction Boolean() sur une valeur.

22
Prakash

Il semble que l'opérateur !! entraîne une double négation.

var foo = "Hello World!";

!foo // Result: false
!!foo // Result: true
21
Steve Harrison

! est "boolean not", ce qui correspond essentiellement à la valeur "enable" de son opposé booléen. La deuxième ! retourne cette valeur. Donc, !!enable signifie "ne pas activer," en vous donnant la valeur de enable en tant que booléen.

18
Annika Backstrom

Je pense qu’il convient de mentionner qu’une condition combinée avec AND logique ET/OU ne renverra pas une valeur booléenne mais le dernier succès ou le premier échec en cas de && et Premier succès ou dernier échec en cas de || de la chaîne de condition.

res = (1 && 2); // res is 2
res = (true && alert) // res is function alert()
res = ('foo' || alert) // res is 'foo'

Pour transformer la condition en un vrai littéral booléen, nous pouvons utiliser la double négation:

res = !!(1 && 2); // res is true
res = !!(true && alert) // res is true
res = !!('foo' || alert) // res is true
17
GreQ

La construction !! est un moyen simple de transformer toute expression JavaScript en Son équivalent booléen. 

Par exemple: !!"he shot me down" === true et !!0 === false.

14
Navin Rauniyar

Ce n'est pas un seul opérateur, c'est deux. Cela équivaut à ce qui suit et constitue un moyen rapide de transtyper une valeur en booléen. 

val.enabled = !(!enable);
11
Justin Johnson

!! utilise l'opération NOT deux fois, ! convertit la valeur en une variable boolean et l'inverse, voici un exemple simple pour voir comment fonctionne !!:

Au début, l'endroit que vous avez:

var zero = 0;

Ensuite, vous faites !0, il sera converti en booléen et évalué à true, car 0 est falsy; vous obtenez donc la valeur inversée et convertie en boolean, de sorte qu'il soit évalué à true.

!zero; //true

mais nous ne voulons pas la version booléenne inversée de la valeur, nous pouvons donc l'inverser à nouveau pour obtenir notre résultat! C'est pourquoi nous utilisons un autre !.

En gros, !!, assurez-vous que la valeur que nous obtenons est un booléen, pas de la fausseté, de la vérité ou de la ficelle, etc.

Donc, c'est comme utiliser la fonction Boolean en javascript, mais un moyen simple et rapide de convertir une valeur en booléen:

var zero = 0;
!!zero; //false
8
Alireza

Les instructions if et while et l'opérateur ? utilisent des valeurs de vérité pour déterminer la branche de code à exécuter. Par exemple, les nombres zéro et NaN et la chaîne vide sont faux, mais les autres nombres et chaînes sont vrais. Les objets sont vrais, mais la valeur non définie et null sont tous les deux faux.

L'opérateur de double négation !! calcule la valeur de vérité d'une valeur. Il s’agit en fait de deux opérateurs, où !!x signifie !(!x) et se comporte comme suit:

  • Si x est une valeur fausse, !x est true et !!x est false.
  • Si x est une valeur vraie, !x est false et !!x est true.

Lorsqu'il est utilisé au niveau supérieur d'un contexte booléen (if, while ou ?), l'opérateur !! est comportementalement non-op. Par exemple, if (x) et if (!!x) signifient la même chose.

Utilisations pratiques

Cependant, il a plusieurs utilisations pratiques.

Une utilisation consiste à compresser avec perte un objet à sa valeur de vérité, afin que votre code ne contienne pas de référence à un gros objet et ne le garde pas en vie. L'affectation de !!some_big_object à une variable au lieu de some_big_object permet de la supprimer pour le ramasse-miettes. Cela est utile pour les cas qui produisent un objet ou une valeur fausse telle que null ou la valeur indéfinie, telle que la détection des fonctionnalités du navigateur.

Une autre utilisation, mentionnée dans une réponse à propos de l'opérateur !! correspondant de C, concerne les outils "lint" qui recherchent les fautes de frappe courantes et les diagnostics d'impression. Par exemple, en C et en JavaScript, quelques fautes de frappe courantes pour les opérations booléennes produisent d'autres comportements dont le résultat n'est pas tout à fait aussi booléen:

  • if (a = b) est une assignation suivie par l'utilisation de la valeur de vérité de b; if (a == b) est une comparaison d'égalité.
  • if (a & b) est un bitwise AND; if (a && b) est un ET logique. 2 & 5 est 0 (une valeur fausse); 2 && 5 est vrai.

L'opérateur !! assure à l'outil anti-peluche que ce que vous avez écrit correspond à ce que vous vouliez dire: effectuez cette opération, puis prenez la valeur de la vérité du résultat.

Une troisième utilisation consiste à produire des éléments logiques XOR et logiques XNOR. En C et en JavaScript, a && b exécute un AND logique (true si les deux côtés sont vrais) et a & b effectue un AND au niveau des bits. a || b exécute un OR logique (vrai si au moins un des vrais), et a | b exécute un OU au niveau du bit. Il existe un XOR au sens binaire (OU exclusif) sous la forme a ^ b, mais il n'y a pas d'opérateur intégré pour logique XOR (vrai si exactement un côté est vrai). Vous pouvez, par exemple, autoriser l'utilisateur à saisir du texte dans exactement l'un des deux champs. Ce que vous pouvez faire est de convertir chacun en une valeur de vérité et de les comparer: !!x !== !!y.

8
Damian Yerrick

Je soupçonne que c’est un reliquat du C++ où les utilisateurs remplacent le! opérateur mais pas l'opérateur bool.

Donc, pour obtenir une réponse négative (ou positive) dans ce cas, vous devez d’abord utiliser le code! opérateur pour obtenir un booléen, mais si vous voulez vérifier le cas positif utilisera !!.

8
Darren Clark

Double négation booléenne. Souvent utilisé pour vérifier si la valeur n'est pas indéfinie.

7
Sergey Ilinsky

!!x est un raccourci pour Boolean(x)

Le premier bang force le moteur js à exécuter Boolean(x) mais a également pour effet secondaire d'inverser la valeur. Donc, le deuxième coup annule l'effet secondaire.

7
Greg Gum

Des tonnes de bonnes réponses ici, mais si vous avez lu jusque-là, cela m'a aidé à «l'obtenir». Ouvrez la console sur Chrome (etc) et commencez à taper:

!(!(1))
!(!(0))
!(!('truthy')) 
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)

Naturellement, cela revient à taper simplement !! quelque chose, mais les parenthèses ajoutées peuvent aider à le rendre plus compréhensible.

7
Warren Davis

Cela oblige tout à être booléen. 

Par exemple:

console.log(undefined); // -> undefined
console.log(!undefined); // -> true
console.log(!!undefined); // -> false

console.log('abc'); // -> abc
console.log(!'abc'); // -> false
console.log(!!'abc'); // -> true

console.log(0 === false); // -> undefined
console.log(!0 === false); // -> false
console.log(!!0 === false); // -> true
5
Khuong

voici un morceau de code de js angulaire 

var requestAnimationFrame = $window.requestAnimationFrame ||
                                $window.webkitRequestAnimationFrame ||
                                $window.mozRequestAnimationFrame;

 var rafSupported = !!requestAnimationFrame;

leur intention est de définir rafSupported sur true ou false en fonction de la disponibilité de la fonction dans requestAnimationFrame 

cela peut être réalisé en vérifiant de la manière suivante en général:

if(typeof  requestAnimationFrame === 'function')
rafSupported =true;
else
rafSupported =false;

le court chemin pourrait utiliser !!

rafSupported = !!requestAnimationFrame ;

donc, si requestAnimationFrame s'est vu attribuer une fonction alors ! requestAnimationFrame serait faux et un de plus! de ce serait vrai

si requestAnimationFrame était évalué non défini, alors ! requestAnimationFrame serait vrai et un de plus! de ce serait faux

Renvoie la valeur booléenne d'une variable.

À la place, la classe Boolean peut être utilisée.

(veuillez lire les descriptions de code)

var X = "test"; // X value is "test" as a String value
var booleanX = !!X // booleanX is `true` as a Boolean value beacuse non-empty strings evaluates as `true` in boolean
var whatIsXValueInBoolean = Boolean(X) // whatIsXValueInBoolean is `true` again
console.log(Boolean(X) === !!X) // writes `true`

À savoir, Boolean(X) = !!X en cours d'utilisation.

Veuillez vérifier l'extrait de code ci-dessous

let a = 0
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a) // writes '0 is NOT true in boolean' value as boolean - So that's true.In boolean 0 means false and 1 means true.
console.log("!!a: ", !!a) // writes 0 value in boolean. 0 means false.
console.log("Boolean(a): ", Boolean(a)) // equals to `!!a`
console.log("\n") // newline

a = 1
console.log("a: ", a)
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes 1 value in boolean
console.log("\n") // newline

a = ""
console.log("a: ", a)
console.log("!a: ", !a) // writes '"" is NOT true in boolean' value as boolean - So that's true.In boolean empty strings, null and undefined values mean false and if there is a string it means true.
console.log("!!a: ", !!a) // writes "" value in boolean
console.log("\n") // newline

a = "test"
console.log("a: ", a) // writes a value in its kind
console.log("!a: ", !a)
console.log("!!a: ", !!a) // writes "test" value in boolean

console.log("Boolean(a) === !!a: ", Boolean(a) === !!a) // writes true

3
efkan

Je voulais juste ajouter que

if(variableThing){
  // do something
}

est le même que

if(!!variableThing){
  // do something
}

Mais cela peut être un problème lorsque quelque chose est indéfini.

// a is undefined, b is empty object.
var a, b = {};

// Both of these give error a.foo is not defined etc.
// you'd see the same behavior for !!a.foo and !!b.foo.bar

a.foo 
b.foo.bar

// This works -- these return undefined

a && a.foo
b.foo && b.foo.bar
b && b.foo && b.foo.bar

Le truc ici est que la chaîne de &&s retournera la première valeur de falsey elle trouve - et cela peut être alimenté en une instruction if, etc. Ainsi, si b.foo est indéfini, il retournera indéfini et ignore l'instruction b.foo.bar et nous n'obtiendrons aucune erreur.

Le retour ci-dessus est indéfini, mais si vous avez une chaîne vide, false, null, 0, indéfini, ces valeurs seront renvoyées et dès que nous les rencontrerons dans la chaîne - [] et {} seront tous les deux vrais.

3
Ryan Taylor

Certains opérateurs de JavaScript effectuent des conversions de types implicites et sont parfois utilisés pour la conversion de types.

L'opérateur unaire ! convertit son opérande en un booléen et le nie.

Ce fait conduit à l'idiome suivant que vous pouvez voir dans votre code source:

!!x // Same as Boolean(x). Note double exclamation mark
3
GibboK

Utilisez logique pas opérateur deux fois
cela signifie! vrai = faux
et !! true = true

2
Abhay Dixit

Après avoir vu toutes ces bonnes réponses, j'aimerais ajouter une autre raison d'utiliser !!. Actuellement, je travaille dans Angular 2-4 (TypeScript) et je veux renvoyer un booléen sous la forme false lorsque mon utilisateur n'est pas authentifié. S'il n'est pas authentifié, la chaîne de jeton serait null ou "". Je peux le faire en utilisant le bloc de code suivant:

public isAuthenticated(): boolean {
   return !!this.getToken();
}
2
Wouter Vanherck
a = 1;
alert(!a) // -> false : a is not not defined
alert(!!a) // -> true : a is not not defined

Pour !a, il vérifie si a estPASdéfini, alors que !!a vérifie si la variable est définie.

!!a est identique à !(!a). Si a est défini, a est true, !a est false et !!a est true.

2
user3698272

Cette question a reçu une réponse assez complète, mais j'aimerais ajouter une réponse qui, j'espère, soit aussi simplifiée que possible, rendant le sens de !! aussi simple à saisir que possible.

Parce que javascript a ce que l’on appelle les valeurs "vérité" et "falsey", il existe des expressions qui, une fois évaluées, donneront une condition vraie ou fausse, même si la valeur ou l’expression examinée n’est pas réellement true ou false.

Par exemple:

if (document.getElementById('myElement')) {
    // code block
}

Si cet élément existe réellement, l'expression sera évaluée comme étant vraie et le bloc de code sera exécuté.

Toutefois:

if (document.getElementById('myElement') == true) {
    // code block
}

... n'aboutira PAS à une condition vraie et le bloc de code ne sera pas exécuté, même si l'élément existe.

Pourquoi? Parce que document.getElementById() est une expression "vérité" qui sera évaluée comme vraie dans cette instruction if(), mais il ne s'agit pas d'une valeur booléenne réelle de true.

Le double "non" dans ce cas est assez simple. C’est tout simplement deux nots dos à dos.

Le premier "inverse" simplement la valeur vérité ou falsey, ce qui donne un type booléen réel, puis le second "le retourne" dans son état d'origine, mais maintenant dans une valeur booléenne réelle. De cette façon, vous avez la cohérence:

if (!!document.getElementById('myElement')) {}

et

if (!!document.getElementById('myElement') == true) {}

les deux retourneront vrai, comme prévu.

1
Klw Wallace

Double ! évalue une variable à sa valeur booléenne. Par exemple, false 0 (zéro), '' ou "" (chaîne vide), null, undefined, NaN est évalué à false . Voir cet article https://www.sitepoint.com/javascript -truthy-falsy/

0
tolotrasmile