web-dev-qa-db-fra.com

Comment !! ~ (et non pas tilde / bang bang tilde) modifie-t-il le résultat d'un appel de méthode Array 'contains / included'?

Si vous lisez les commentaires sur la page jQuery inArrayici , il y a une déclaration intéressante:

!!~jQuery.inArray(Elm, arr) 

Maintenant, je crois qu'un point d'exclamation double convertira le résultat en type boolean, avec la valeur de true. Ce que je ne comprends pas, c'est à quoi sert le tilde (~) opérateur dans tout cela?

var arr = ["one", "two", "three"];
if (jQuery.inArray("one", arr) > -1) { alert("Found"); }

Refactorisation de l'instruction if:

if (!!~jQuery.inArray("one", arr)) { alert("Found"); }

Panne:

jQuery.inArray("one", arr)     // 0
~jQuery.inArray("one", arr)    // -1 (why?)
!~jQuery.inArray("one", arr)   // false
!!~jQuery.inArray("one", arr)  // true

J'ai également remarqué que si je mets le tilde devant, le résultat est -2.

~!!~jQuery.inArray("one", arr) // -2

Je ne comprends pas le but du tilde ici. Quelqu'un peut-il l'expliquer ou me diriger vers une ressource?

93
user717236

L'opérateur tilde ne fait pas du tout partie de jQuery - c'est un opérateur NOT au niveau du bit dans JavaScript lui-même.

Voir Le grand mystère du tilde (~).

Vous obtenez des nombres étranges dans vos expériences parce que vous effectuez une opération logique au niveau du bit sur un entier (qui, pour autant que je sache, peut être stocké comme complément à deux ou quelque chose comme ça ...)

Complément à deux explique comment représenter un nombre en binaire. Je pense que j'avais raison.

55
p.g.l.hall

Il y a une raison particulière pour laquelle vous verrez parfois ~ appliqué devant $.inArray.

Fondamentalement,

~$.inArray("foo", bar)

est une façon plus courte de faire

$.inArray("foo", bar) !== -1

$.inArray renvoie l'index de l'élément dans le tableau si le premier argument est trouvé, et il renvoie -1 s'il n'est pas trouvé. Cela signifie que si vous recherchez un booléen de "cette valeur est-elle dans le tableau?", Vous ne pouvez pas faire de comparaison booléenne, car -1 est une valeur véridique, et lorsque $ .inArray renvoie 0 (une valeur falsifiée ), cela signifie qu'il se trouve réellement dans le premier élément du tableau.

Appliquer le ~ l'opérateur au niveau du bit provoque -1 devenir 0, et fait que 0 devienne `-1. Ainsi, ne pas trouver la valeur dans le tableau et appliquer le NOT au niveau du bit entraîne une valeur fausse (0), et toutes les autres valeurs renverront des nombres non 0 et représenteront un résultat véridique.

if (~$.inArray("foo", ["foo",2,3])) {
    // Will run
}

Et cela fonctionnera comme prévu.

117
Yahel

!!~expr Est évalué à false lorsque expr est -1 Sinon true.
C'est la même chose que expr != -1, Seulement cassé *


Cela fonctionne parce que opérations binaires JavaScript convertit les opérandes en entiers signés 32 bits au format complément à deux. Ainsi !!~-1 Est évalué comme suit:

   -1 = 1111 1111 1111 1111 1111 1111 1111 1111b // two's complement representation of -1
  ~-1 = 0000 0000 0000 0000 0000 0000 0000 0000b // ~ is bitwise not (invert all bits)
   !0 = true                                     // ! is logical not (true for falsy)
!true = false                                    // duh

Une valeur autre que -1 Aura au moins un bit mis à zéro; l'inverser créera une valeur vraie; appliquer deux fois l'opérateur ! à une valeur true renvoie booléen true.

Lorsqu'il est utilisé avec .indexOf() et nous voulons seulement vérifier si le résultat est -1 Ou non:

!!~"abc".indexOf("d") // indexOf() returns -1, the expression evaluates to false
!!~"abc".indexOf("a") // indexOf() returns  0, the expression evaluates to true
!!~"abc".indexOf("b") // indexOf() returns  1, the expression evaluates to true

* !!~8589934591 A la valeur false, donc cela abomination ne peut pas être utilisé de manière fiable pour tester -1.

102
Salman A

~foo.indexOf(bar) est un raccourci courant pour représenter foo.contains(bar) car la fonction contains n'existe pas.

Typiquement, la conversion en booléen n'est pas nécessaire en raison du concept JavaScript des valeurs de "falsification". Dans ce cas, il est utilisé pour forcer la sortie de la fonction à être true ou false.

32
zzzzBov

jQuery.inArray() renvoie -1 pour "non trouvé", dont le complément (~) est 0. Ainsi, ~jQuery.inArray() renvoie une valeur fausse (0) Pour "non trouvé" et une valeur vraie (un entier négatif) pour "trouvé". !! Formalisera alors la fausse/vérité en vrai booléen false/true. Ainsi, !!~jQuery.inArray() donnera true pour "trouvé" et false pour "non trouvé".

18
Amadan

Le ~ Pour les 4 octets int est égal à cette formule -(N+1)

DONC

~0   = -(0+1)   // -1
~35  = -(35+1)  // -36 
~-35 = -(-35+1) //34 
12
Mina Gabriel

L'opérateur ~ Est l'opérateur de complément au niveau du bit. Le résultat entier de inArray() est soit -1, lorsque l'élément n'est pas trouvé, soit un entier non négatif. Le complément binaire de -1 (représenté en binaire comme tous les 1 bits) est zéro. Le complément binaire de tout entier non négatif est toujours non nul.

Ainsi, !!~i Sera true lorsque l'entier "i" est un entier non négatif et false lorsque "i" est exactement -1.

Notez que ~ Contraint toujours son opérande à un entier; c'est-à-dire qu'il force les valeurs à virgule flottante non entières en entiers, ainsi que les valeurs non numériques.

10
Pointy

Tilde n'est PAS au niveau du bit - il inverse chaque bit de la valeur. En règle générale, si vous utilisez ~ sur un nombre, son signe sera inversé, puis 1 sera soustrait.

Ainsi, lorsque vous faites ~0, vous obtenez -1 (0 inversé est -0, soustrayez 1 est -1).

Il s'agit essentiellement d'une manière élaborée et micro-optimisée d'obtenir une valeur toujours booléenne.

10
Joe

Vous avez raison: ce code renverra false lorsque l'appel indexOf renvoie -1; sinon true.

Comme vous le dites, il serait beaucoup plus judicieux d'utiliser quelque chose comme

return this.modifiedPaths.indexOf(path) !== -1;
8
LukeH

Le ~ L'opérateur est l'opérateur NOT au niveau du bit. Cela signifie qu'il prend un nombre sous forme binaire et transforme tous les zéros en uns et les uns en zéros.

Par exemple, le nombre 0 en binaire est 0000000, tandis que -1 est 11111111. De même, 1 est 00000001 en binaire, tandis que -2 est 11111110.

6
Frxstrem

Je suppose qu'il est là parce qu'il est plus court de quelques caractères (que les auteurs de la bibliothèque recherchent toujours). Il utilise également des opérations qui ne prennent que quelques cycles machine lorsqu'elles sont compilées dans le code natif (par opposition à la comparaison avec un nombre.)

Je suis d'accord avec une autre réponse selon laquelle c'est une exagération mais peut-être peut-être logique dans une boucle serrée (nécessite une estimation du gain de performance, sinon, cela pourrait se révéler être une optimisation prématurée.)

3
Alexander Pavlov

Je suppose que, puisqu'il s'agit d'une opération au niveau du bit, c'est le moyen le plus rapide (bon marché sur le plan des calculs) de vérifier si le chemin apparaît dans modifiedPaths.

2
panos2point0

Comme (~(-1)) === 0, alors:

!!(~(-1)) === Boolean(~(-1)) === Boolean(0) === false
1
Engineer