J'ai vu un code qui semble utiliser un opérateur , je ne reconnais pas, sous la forme de deux points d'exclamation, comme suit: !!
. Quelqu'un peut-il me dire ce que fait cet opérateur?
Le contexte dans lequel j'ai vu cela était,
this.vertical = vertical !== undefined ? !!vertical : this.vertical;
javascript
operators
Théorie de l'hexagone
la source
la source
if(vertical !== undefined) this.vertical = Boolean(vertical);
- il est beaucoup plus propre et plus clair de ce qui se passe, ne nécessite aucune affectation inutile, est entièrement standard et est tout aussi rapide (sur FF actuel et Chrome) jsperf.com/boolean-conversion-speed .Boolean(5/0)
n'est pas la même chose que!!5/0
!!5/0
produireInfinity
plutôt quetrue
, comme produit parBoolean(5/0)
.!!5/0
est équivalent à(!!5)/0
- akatrue/0
- car l'!
opérateur a une priorité plus élevée que l'/
opérateur. Si vous vouliez booléeniser en5/0
utilisant un double coup, vous auriez besoin d'utiliser!!(5/0)
.Réponses:
Convertit
Object
enboolean
. Si elle était Falsey (par exemple0
,null
,undefined
, etc.), il serafalse
, par ailleurs,true
.Ce
!!
n'est donc pas un opérateur, c'est juste l'!
opérateur deux fois.Exemple du monde réel "Tester la version IE":
Si vous ⇒
Mais si vous ⇒
la source
C'est une façon horriblement obscure de faire une conversion de type.
!
n'est pas . Il en!true
est de mêmefalse
et!false
esttrue
.!0
esttrue
, et!1
estfalse
.Vous convertissez donc une valeur en booléen, puis vous l'inversez, puis vous l'inversez à nouveau.
la source
userId ? true : false
indique plus clairement qu'il y a une conversion en cours et gère le cas où la valeur de userId pourrait avoir été explicitement définie surundefined
!!var
dansBoolean(var)
.. et!!
est plus rapide (moins d' instructions à traiter) et plus court que les solutions de rechange.userId != 0
est vrai pournull
,NaN
etundefined
, mais faux pourfalse
. Si vous voulez exactement ce comportement, vous devriez probablement être explicite à ce sujet. Mais même si cela fonctionnait exactement de la même manière!!userId
, il n'est pas clair si vous voulez que ces valeurs apparaissent fausses ici, ou si vous n'avez simplement pas pris en compte les règles de conversion de type Javascript.!!expr
renvoie une valeur booléenne (true
oufalse
) selon la véracité de l'expression. Il est plus logique lorsqu'il est utilisé sur des types non booléens. Considérez ces exemples, en particulier le 3e exemple et les suivants:la source
!!new Boolean(false) // true
!!Boolean(false) // false
new Boolean(false)
est un objet et un objet est véridique même s'il contient une valeur falsifiée!String
,Number
,Date
, etc.) sont destinés à être appelable comme des fonctions aussi, mais dans ce cas , le résultat est différent!new Boolean(false)
retourne unobject
certain tempsBoolean(false)
renvoie la primitivefalse
. J'espère que cela a du sens.Préparez du thé:
!!
n'est pas un opérateur. C'est la double utilisation de!
- qui est l'opérateur logique "non".En théorie:
!
détermine la "vérité" de ce qu'une valeur n'est pas:La vérité est que ce
false
n'est pas le castrue
(c'est pourquoi cela se!false
traduit partrue
)La vérité est que ce
true
n'est pas le casfalse
(c'est pourquoi cela se!true
traduit parfalse
)!!
détermine la « vérité » de ce qu'est une valeur non pas:La vérité est que
true
ce n'est pas nontrue
(c'est pourquoi les!!true
résultats danstrue
)La vérité est que
false
ce n'est pas nonfalse
(c'est pourquoi les!!false
résultats dansfalse
)Ce que nous voulons déterminer dans la comparaison, c'est la «vérité» sur la valeur d'une référence, et non la 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 typeofboolean
.En pratique:
Considérons une fonction concise qui détecte la fonctionnalité (et dans ce cas, la compatibilité de la plate-forme) au moyen du typage dynamique (aka "duck typing"). Nous voulons écrire une fonction qui retourne
true
si le navigateur d'un utilisateur prend en charge l'<audio>
élément HTML5 , mais nous ne voulons pas que la fonction génère une erreur si elle<audio>
n'est pas définie; et nous ne voulons pas utilisertry ... catch
pour gérer les erreurs possibles (car elles sont grossières); et nous ne voulons pas non plus utiliser une vérification à l'intérieur de 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:
Chaque fonction accepte un argument pour a
<tag>
et anattribute
à 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 les moyens légèrement plus performants de vérifier si l'objet en question a une propriété. Il y a deux façons de faire ça:
Nous nous éloignons ...
Aussi rares que soient ces situations, il peut exister quelques scénarios où le moyen le plus concis, le plus performant et donc le plus préféré d'obtenir
true
d'une valeur non booléenne, peut-être indéfinie, est bien d'utiliser!!
. Espérons que cela clarifie ridiculement les choses.la source
if()
instruction transforme déjà l'expression en booléen, le fait de transposer explicitement la valeur de retour d'une fonction de test en booléen est redondant - puisque "véracité" === true en ce qui concerne uneif()
instruction de toute façon. Ou est-ce que je manque un scénario où vous avez besoin d'une expression véridique pour être réellement booléentrue
?if()
instructions @TomAuger font un cast booléen contre les valeurs de falsey, mais disons que vous voulez réellement définir un drapeau booléen sur un objet - il ne le cast pas comme le fait uneif()
instruction. Par exempleobject.hasTheThing = !!castTheReturnValToBoolNoMatterWhat()
, définirait soittrue
oufalse
au lieu de la valeur de retour réelle. Un autre exemple est peut-être que tous les administrateurs sontid
de0
et les non-administrateurs sont id1
ou supérieur. Pour obtenirtrue
si quelqu'un n'est pas un administrateur, vous pouvez le faireperson.isNotAdmin = !!admin.id
. Peu de cas d'utilisation, mais c'est concis quand il y en a.!!
convertit la valeur à sa droite en sa valeur booléenne équivalente. (Pensez à la manière du pauvre homme de "taper des caractères"). Son intention est généralement de transmettre au lecteur que le code ne se soucie pas ce que la valeur est dans la variable, mais ce que c'est la valeur « vérité » est.la source
!
retourne toujours la valeur vers la droite. Dans le cas d'un booléen, le plus à droite!
nie la valeur, tandis que le plus à gauche la!
nie à nouveau. L'effet net est qu'il n'y a pas de changement, mais la plupart des moteurs génèrent des codes op pour la double négation.if(0){...
Javascript sait déjà que c'est faux. Pourquoi vaut-il mieux direif(!!0){...
?!!foo
applique l'opérateur unary not deux fois et est utilisé pour convertir en type booléen similaire à l'utilisation d'unaire plus+foo
pour convertir en nombre et concaténer une chaîne vide''+foo
pour convertir en chaîne.Au lieu de ces hacks, vous pouvez également utiliser les fonctions constructeurs correspondant aux types primitifs ( sans utiliser
new
) pour convertir explicitement des valeurs, c'est-à-direla source
new
- comme mentionné explicitement dans ma réponsex="0"
juste faire:x=!!+x; //false
qui est le même queBoolean(Number(x))
Number (ou + x) convertit la chaîne "0" en 0, ce qui est évalué comme faux, puis booléen (!! x) le transforme directement en booléen. Peasy facile!!!+x
vsx !== "0"
?Autant de réponses qui font la moitié du travail. Oui,
!!X
pourrait être lu comme "la véracité de X [représentée comme un booléen]". Mais!!
n'est pas, pratiquement parlant, si important pour déterminer si une seule variable est (ou même si plusieurs variables sont) véridiques ou fausses.!!myVar === true
est le même que justemyVar
. La comparaison!!X
avec un "vrai" booléen n'est pas vraiment utile.Ce que vous gagnez,
!!
c'est la possibilité de vérifier la véracité de plusieurs variables les unes par rapport aux autres de manière reproductible, standardisée (et compatible avec JSLint).Simplement lancer :(
C'est...
0 === false
estfalse
.!!0 === false
esttrue
.Ce qui précède n'est pas si utile.
if (!0)
vous donne les mêmes résultats queif (!!0 === false)
. Je ne peux pas penser à un bon cas pour convertir une variable en booléen, puis comparer à un "vrai" booléen.Voir "== et! =" Dans les instructions de JSLint (note: Crockford déplace un peu son site; ce lien est susceptible de mourir à un moment donné) pour un peu sur pourquoi:
Notez qu'il existe des cas non intuitifs où un booléen sera converti en un nombre (
true
est converti en1
etfalse
en0
) lors de la comparaison d'un booléen en un nombre. Dans ce cas,!!
pourrait être mentalement utile. Bien que, encore une fois, ce sont des cas où vous comparez un non-booléen à un booléen dur, ce qui est, imo, une grave erreur.if (-1)
est toujours le chemin à parcourir ici.Et les choses deviennent encore plus folles selon votre moteur. WScript, par exemple, remporte le prix.
En raison de l' historique jive de Windows , cela produira -1 dans une boîte de message! Essayez-le dans une invite cmd.exe et voyez! Mais
WScript.echo(-1 == test())
vous donne toujours 0, ou WScriptfalse
. Détourne le regard. C'est hideux.Comparaison de la véracité :)
Mais que se passe-t-il si j'ai deux valeurs dont je dois vérifier la véracité / la fausseté égales?
Imaginez que nous avons
myVar1 = 0;
etmyVar2 = undefined;
.myVar1 === myVar2
est0 === undefined
et est évidemment faux.!!myVar1 === !!myVar2
est!!0 === !!undefined
et est vrai! Même vérité! (Dans ce cas, les deux "ont une vérité de fausseté".)Donc, le seul endroit où vous auriez vraiment besoin d'utiliser des "variables booléennes" serait si vous aviez une situation où vous vérifiez si les deux variables ont la même véracité, non? C'est-à-dire, utilisez
!!
si vous avez besoin de voir si deux vars sont à la fois véridiques ou fausses (ou non), c'est-à-dire de véracité égale (ou non) .Je ne peux pas penser à un excellent cas d'utilisation non artificiel pour cette désinvolture. Vous avez peut-être des champs "liés" dans un formulaire?
Alors maintenant, si vous avez une vérité pour les deux ou une fausse pour le nom et l'âge du conjoint, vous pouvez continuer. Sinon, vous n'avez qu'un seul champ avec une valeur (ou un mariage arrangé très tôt) et devez créer une erreur supplémentaire sur votre
errorObjects
collection.EDIT 24 oct 2017, 6 fév 19:
Bibliothèques tierces qui attendent des valeurs booléennes explicites
Voici un cas intéressant ...
!!
pourrait être utile lorsque des bibliothèques tierces attendent des valeurs booléennes explicites.Par exemple, False dans JSX (React) a une signification spéciale qui n'est pas déclenchée par une simple fausseté. Si vous avez essayé de renvoyer quelque chose comme ce qui suit dans votre JSX, en attendant un int dans
messageCount
...{messageCount && <div>You have messages!</div>}
... vous pourriez être surpris de voir React effectuer un rendu
0
lorsque vous n'avez aucun message. Vous devez explicitement retourner false pour que JSX ne soit pas rendu. L'instruction ci-dessus renvoie0
, que JSX rend avec bonheur, comme il se doit. Cela ne peut pas dire que vous n'en aviez pasCount: {messageCount && <div>Get your count to zero!</div>}
(ou quelque chose de moins artificiel).Une solution implique le bangbang, qui coercé
0
en!!0
, qui estfalse
:{!!messageCount && <div>You have messages!</div>}
Les documents de JSX vous suggèrent d'être plus explicite, d'écrire du code auto-commenté et d'utiliser une comparaison pour forcer à un booléen.
{messageCount > 0 && <div>You have messages!</div>}
Je suis plus à l'aise pour gérer moi-même la fausseté avec un ternaire -
{messageCount ? <div>You have messages!</div> : false}
Même chose dans Typescript: si vous avez une fonction qui retourne un booléen (ou si vous assignez une valeur à une variable booléenne), vous [généralement] ne pouvez pas retourner / assigner une valeur booléenne-y; ce doit être un booléen fortement typé. Cela signifie que si siff
myObject
est fortement typé ,return !myObject;
fonctionne pour une fonction renvoyant un booléen, maisreturn myObject;
ne le fait pas. Vous devezreturn !!myObject
correspondre aux attentes de Typescript.Gardez à l'esprit que ce sont des conventions JSX et Typescript , pas celles inhérentes à JavaScript .
Mais si vous voyez des
0
s étranges dans votre JSX rendu, pensez à une gestion de fausseté lâche.la source
if (!!window.Worker)
true
«extérieurement» fonctionnent exactement de la même manière dans unif
. Je continue d'essayer, mais je ne peux pas penser à une raison pour préférer jeter la vérité à une valeur booléenne en dehors du type de cas compliqué "comparer les vérités" ci-dessus, sauf pour la lisibilité si vous réutilisez la valeur plus tard, comme dans l'q
exemple de la bibliothèque . Mais même alors, c'est un raccourci avec perte d'informations, et je dirais que vous feriez mieux d'évaluer la véracité à chaque fois.C'est juste l'opérateur NOT logique, deux fois - il est utilisé pour convertir quelque chose en booléen, par exemple:
la source
Il convertit le suffixe en valeur booléenne.
la source
C'est une double
not
opération. Le premier!
convertit la valeur en booléen et inverse sa valeur logique. Le second!
inverse la valeur logique.la source
Il semble que l'
!!
opérateur entraîne une double négation.la source
Il simule le comportement de la
Boolean()
fonction de casting. La premièreNOT
renvoie une valeur booléenne quel que soit l'opérande qui lui est donné. La secondeNOT
annule cetteBoolean
valeur et donne ainsi latrue
valeur booléenne d'une variable. Le résultat final est identique à l'utilisation de laBoolean()
fonction sur une valeur.la source
! est "booléen non", qui transcrit essentiellement la valeur de "enable" à son opposé booléen. La deuxième ! inverse cette valeur. Donc,
!!enable
signifie «pas activé», ce qui vous donne la valeur d'enable
un booléen.la source
Je pense qu'il convient de mentionner qu'une condition combinée avec ET / OU logique ne renverra pas de valeur booléenne mais le dernier succès ou le premier échec en cas de && et le premier succès ou le dernier échec en cas de || de la chaîne de condition.
Afin de convertir la condition en un vrai littéral booléen, nous pouvons utiliser la double négation:
la source
!!
il utilise l'NOT
opération deux fois ensemble,!
convertit la valeur en aboolean
et l'inverse, voici un exemple simple pour voir comment ça!!
marche:Au début, l'endroit que vous avez:
Ensuite
!0
, il sera converti en booléen et évalué entrue
, car 0 estfalsy
, donc vous obtenez la valeur inversée et converti en booléen, donc il est évalué entrue
.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 en utilisons un autre
!
.Fondamentalement,
!!
assurez-vous que la valeur que nous obtenons est booléenne, pas fausse, véridique ou chaîne, etc.C'est donc comme utiliser la
Boolean
fonction en javascript, mais un moyen simple et plus court de convertir une valeur en booléen:la source
La
!!
construction est un moyen simple de transformer n'importe quelle expression JavaScript en son équivalent booléen.Par exemple:
!!"he shot me down" === true
et!!0 === false
.la source
0 === false
c'est faux et!!0 === false
c'est vrai.Ce n'est pas un seul opérateur, c'est deux. C'est équivalent à ce qui suit et est un moyen rapide de convertir une valeur en booléen.
la source
Je soupçonne que c'est un reste de C ++ où les gens remplacent le! mais pas l'opérateur booléen.
Donc, pour obtenir une réponse négative (ou positive) dans ce cas, vous devez d'abord utiliser le! pour obtenir un booléen, mais si vous voulez vérifier le cas positif, utilisez !!.
la source
Les
if
etwhile
déclarations et l'?
utilisation des valeurs de vérité opérateur pour déterminer quelle 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 indéfinie etnull
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:x
est une valeur fausse,!x
esttrue
et!!x
estfalse
.x
est une vraie valeur,!x
estfalse
et!!x
esttrue
.Lorsqu'il est utilisé au niveau supérieur d'un contexte booléen (
if
,while
ou?
), l'!!
opérateur est une behaviorally no-op. Par exemple,if (x)
etif (!!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 maintienne pas en vie. Affecter
!!some_big_object
à une variable au lieu desome_big_object
laisser tomber pour le garbage collector. Cela est utile pour les cas qui produisent un objet ou une valeur fausse telle quenull
ou la valeur indéfinie, telle que la détection des fonctionnalités du navigateur.Une autre utilisation, que j'ai mentionnée dans une réponse à propos de l'
!!
opérateur correspondant de C , est avec 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 la sortie n'est pas aussi booléenne:if (a = b)
est l'affectation suivie de l'utilisation de la valeur de vérité deb
;if (a == b)
est une comparaison d'égalité.if (a & b)
est un ET au niveau du bit;if (a && b)
est un ET logique.2 & 5
est0
(une fausse valeur);2 && 5
est vrai.L'
!!
opérateur rassure l'outil lint que ce que vous avez écrit est ce que vous vouliez dire: faites cette opération, puis prenez la valeur de vérité du résultat.Une troisième utilisation consiste à produire un XOR logique et un XNOR logique. En C et en JavaScript,
a && b
effectue un ET logique (vrai si les deux côtés sont vrais) eta & b
effectue un ET au niveau du bit.a || b
effectue un OU logique (vrai si au moins un est vrai) eta | b
effectue un OU au niveau du bit. Il existe un XOR au niveau du bit (OU exclusif)a ^ b
, mais il n'y a pas d'opérateur intégré pour le XOR logique (vrai si exactement un côté est vrai). Vous pouvez, par exemple, vouloir autoriser l'utilisateur à saisir du texte dans exactement l'un des deux champs. Ce que vous pouvez faire est de convertir chacun à une valeur de vérité et de les comparer:!!x !== !!y
.la source
Double négation booléenne. Souvent utilisé pour vérifier si la valeur n'est pas indéfinie.
la source
Des tonnes de bonnes réponses ici, mais si vous avez lu jusqu'ici, cela m'a aidé à «l'obtenir». Ouvrez la console sur Chrome (etc.) et commencez à taper:
Naturellement, ce sont les mêmes que de simplement taper !! someThing, mais les parenthèses ajoutées pourraient aider à le rendre plus compréhensible.
la source
!!x
est un raccourci pourBoolean(x)
Le premier coup oblige le moteur js à fonctionner
Boolean(x)
mais a également pour effet secondaire d'inverser la valeur. Ainsi, le deuxième coup annule l'effet secondaire.la source
Cela oblige tout à booléen.
Par exemple:
la source
Cette question a reçu une réponse assez complète, mais j'aimerais ajouter une réponse qui, je l'espère, est aussi simplifiée que possible, en donnant le sens de !! aussi simple à saisir que possible.
Parce que javascript a ce qu'on appelle des valeurs "véridiques" et "falsey", il existe des expressions qui, lorsqu'elles sont évaluées dans d'autres expressions, entraîneront une condition vraie ou fausse, même si la valeur ou l'expression examinée n'est pas réellement
true
oufalse
.Par exemple:
Si cet élément existe réellement, l'expression sera évaluée comme vraie et le bloc de code sera exécuté.
Toutefois:
... n'entraînera 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()
c'est une expression "véridique" qui sera évaluée comme vraie dans cetteif()
déclaration, mais ce n'est pas une valeur booléenne réelle detrue
.Le double "non" dans ce cas est assez simple. C'est simplement deux
not
s dos à dos.Le premier "inverse" simplement la valeur de vérité ou de falsey, résultant en un type booléen réel, puis le second le "retourne" à nouveau à son état d'origine, mais maintenant dans une valeur booléenne réelle. De cette façon, vous avez de la cohérence:
et
retournera à la fois vrai, comme prévu.
la source
Je voulais juste ajouter ça
est le même que
Mais cela peut être un problème lorsque quelque chose n'est pas défini.
L'astuce ici est que la chaîne de
&&
s retournera la première valeur de falsey qu'elle trouve - et cela peut être alimenté à une instruction if etc. Donc si b.foo n'est pas défini, il retournera non défini et sautera l'b.foo.bar
instruction, et nous n'obtiendrons pas Erreur.Les valeurs ci-dessus renvoient undefined mais si vous avez une chaîne vide, false, null, 0, undefined, ces valeurs seront renvoyées et dès que nous les rencontrerons dans la chaîne -
[]
et{}
sont toutes les deux "véridiques" et nous continuerons dans le soi-disant " && chaîne "à la valeur suivante à droite.PS Une autre façon de faire la même chose est que
(b || {}).foo
, si b n'est pas défini, alors ceb || {}
sera le cas{}
, et vous accéderez à une valeur dans un objet vide (pas d'erreur) au lieu d'essayer d'accéder à une valeur dans "non défini" (provoque une erreur ). Donc,(b || {}).foo
c'est la même choseb && b.foo
et((b || {}).foo || {}).bar
c'est la même chose queb && b.foo && b.foo.bar
.la source
({}).anything
donneraundefined
Après avoir vu toutes ces bonnes réponses, je voudrais ajouter une autre raison d'utiliser
!!
. Actuellement, je travaille en Angular 2-4 (TypeScript) et je veux retourner un booléen commefalse
lorsque mon utilisateur n'est pas authentifié. S'il n'est pas authentifié, la chaîne de jetons seraitnull
ou""
. Je peux le faire en utilisant le bloc de code suivant:la source
voici un morceau de code de js angulaire
leur intention est de définir rafSupported sur true ou false en fonction de la disponibilité de la fonction dans requestAnimationFrame
il peut être réalisé en vérifiant de la manière suivante en général:
le chemin court pourrait être d'utiliser !!
donc si requestAnimationFrame a été affecté à une fonction, alors! requestAnimationFrame serait faux et un de plus! ce serait vrai
si requestAnimationFrame était indéfini, alors! requestAnimationFrame serait vrai et un de plus! ce serait faux
la source
Certains opérateurs en JavaScript effectuent des conversions de type implicites et sont parfois utilisés pour la conversion de type.
L'
!
opérateur unaire convertit son opérande en booléen et le nie.Ce fait conduit à l'idiome suivant que vous pouvez voir dans votre code source:
la source
Utilisez deux fois l'opérateur logique,
cela signifie! True = false
et !! true = true
la source
Renvoie la valeur booléenne d'une variable.
Au lieu de cela, la
Boolean
classe peut être utilisée.(veuillez lire les descriptions des codes)
À savoir,
Boolean(X) = !!X
en cours d'utilisation.Veuillez vérifier l'extrait de code ci-dessous ↓
la source