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 :
!!
détermine la "vérité" de ce qu'est une valeur pas pas :
Ce que nous souhaitons déterminer dans la comparaison, c'est la "vérité" à propos de 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ù l'on peut vouloir connaître la vérité sur une valeur, même si l'on s'attend à ce que la valeur soit false
(ou falsey), ou si l'on s'attend à ce que la valeur ne soit pas de typeof boolean
.
En pratique :
Considérons une fonction concise qui détecte la fonctionnalité d'une caractéristique (et dans ce cas, la compatibilité avec la plate-forme) au moyen de la fonction dactylographie dynamique (alias "dactylographie du canard"). Nous voulons écrire une fonction qui renvoie true
si le navigateur de l'utilisateur prend en charge la norme HTML5 <audio>
mais nous ne voulons pas que la fonction génère une erreur si l'élément <audio>
est indéfini ; et nous ne voulons pas utiliser try ... catch
pour gérer les erreurs éventuelles (parce qu'elles sont grossières) ; et aussi nous ne voulons pas utiliser une vérification à l'intérieur de la fonction qui ne révélerait pas systématiquement la vérité sur la caractéristique (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 un <tag>
et un attribute
à rechercher, mais ils renvoient chacun des valeurs différentes en fonction de ce que les comparaisons déterminent.
Mais ce n'est pas tout !
Certains d'entre vous ont probablement remarqué que dans cet exemple spécifique, on pourrait simplement vérifier la présence d'une propriété à l'aide de la fonction légèrement plus performant les moyens de vérifier si l'objet en question a une propriété. Il y a deux façons de procéder :
// 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 du sujet...
Aussi 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 préférable d'obtenir true
à partir d'une valeur non booléenne, éventuellement indéfinie, se fait en utilisant la fonction !!
. J'espère que cela sera ridiculement clair.
1310 votes
Souviens-toi de "bang, bang tu es booléen".
117 votes
Pour mémoire, ne faites pas ce qui est cité. Faites ce qui suit
if(vertical !== undefined) this.vertical = Boolean(vertical);
- il est beaucoup plus propre et plus clair, ne nécessite aucune affectation inutile, est tout à fait standard, et est tout aussi rapide (sur les versions actuelles de FF et Chrome) jsperf.com/vitesse de conversion booléenne .0 votes
"Tout programmeur digne de ce nom devrait savoir ce qui se passe..." - cela aide parfois le compilateur à générer un meilleur code dans les langages compilés. Je sais qu'il était recommandé par Microsoft lors de l'utilisation de code C, car il générait le meilleur code. (C'est probablement toujours le cas, mais je n'arrive pas à trouver la référence pour le moment).
107 votes
! ! n'est pas un opérateur. Il s'agit simplement de l'opérateur ! deux fois.
77 votes
@schabluk, pour mémoire, ordre des opérations est la raison pour laquelle
!!5/0
produitInfinity
plutôt quetrue
, tel que produit parBoolean(5/0)
.!!5/0
est équivalent à(!!5)/0
-- aliastrue/0
-- en raison de la!
ayant une priorité supérieure à celle de l'opérateur/
opérateur. Si vous vouliez booléaniser5/0
en utilisant un double-bang, il faut utiliser!!(5/0)
.0 votes
En d'autres termes, !!vertical vous donne une valeur booléenne indiquant si "vertical" est défini ou non.
2 votes
Que signifie ! !(x) en C (notamment dans le noyau Linux) ?
0 votes
Pour mémoire, Boolean(5/0) n'est pas le -
2 votes
S
!!value === Boolean(value)
30 votes
@
6 votes
@
0 votes
P
0 votes
I
0 votes
@ I
0 votes
I
0 votes
I
0 votes
!