[ACCEPTED]-How does !!~ (not not tilde/bang bang tilde) alter the result of a 'contains/included' Array method call?-bitwise-operators
There's a specfic reason you'll sometimes 17 see ~
applied in front of $.inArray
.
Basically,
~$.inArray("foo", bar)
is 16 a shorter way to do
$.inArray("foo", bar) !== -1
$.inArray
returns the index of 15 the item in the array if the first argument 14 is found, and it returns -1 if its not found. This 13 means that if you're looking for a boolean 12 of "is this value in the array?", you can't 11 do a boolean comparison, since -1 is a truthy 10 value, and when $.inArray returns 0 (a falsy 9 value), it means its actually found in the 8 first element of the array.
Applying the 7 ~
bitwise operator causes -1
to become 0
, and 6 causes 0 to become `-1. Thus, not finding 5 the value in the array and applying the 4 bitwise NOT results in a falsy value (0), and 3 all other values will return non-0 numbers, and 2 will represent a truthy result.
if (~$.inArray("foo", ["foo",2,3])) {
// Will run
}
And it'll 1 work as intended.
!!~expr
evaluates to false
when expr
is -1
otherwise true
.
It 11 is same as expr != -1
, only broken*
It works because 10 JavaScript bitwise operations convert the operands to 32-bit signed integers 9 in two's complement format. Thus !!~-1
is evaluated 8 as follows:
-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
A value other than -1
will have 7 at least one bit set to zero; inverting 6 it will create a truthy value; applying 5 !
operator twice to a truthy value returns 4 boolean true.
When used with .indexOf()
and we only 3 want to check if result is -1
or not:
!!~"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
evaluates 2 to false so this abomination cannot be reliably used 1 to test for -1
.
The tilde operator isn't actually part of 8 jQuery at all - it's a bitwise NOT operator 7 in JavaScript itself.
See The Great Mystery of the Tilde(~).
You are getting 6 strange numbers in your experiments because 5 you are performing a bitwise logical operation 4 on an integer (which, for all I know, may 3 be stored as two's complement or something 2 like that...)
Two's complement explains how to represent 1 a number in binary. I think I was right.
~foo.indexOf(bar)
is a common shorthand to represent foo.contains(bar)
because 5 the contains
function doesn't exist.
Typically the 4 cast to boolean is unnecessary due to JavaScript's 3 concept of "falsy" values. In this case 2 it's used to force the output of the function 1 to be true
or false
.
jQuery.inArray()
returns -1
for "not found", whose complement 5 (~
) is 0
. Thus, ~jQuery.inArray()
returns a falsy value (0
) for 4 "not found", and a truthy value (a negative 3 integer) for "found". !!
will then formalise 2 the falsy/truthy into real boolean false
/true
. So, !!~jQuery.inArray()
will 1 give true
for "found" and false
for "not found".
The ~
for all 4 bytes int
is equal to this formula 1 -(N+1)
SO
~0 = -(0+1) // -1
~35 = -(35+1) // -36
~-35 = -(-35+1) //34
Tilde is bitwise NOT - it inverts each bit 6 of the value. As a general rule of thumb, if 5 you use ~
on a number, its sign will be inverted, then 4 1 will be subtracted.
Thus, when you do ~0
, you 3 get -1 (0 inverted is -0, subtract 1 is 2 -1).
It's essentially an elaborate, super-micro-optimised 1 way of getting a value that's always Boolean.
The ~
operator is the bitwise complement 11 operator. The integer result from inArray()
is either 10 -1, when the element is not found, or some 9 non-negative integer. The bitwise complement 8 of -1 (represented in binary as all 1 bits) is 7 zero. The bitwise-complement of any non-negative 6 integer is always non-zero.
Thus, !!~i
will be 5 true
when integer "i" is a non-negative integer, and 4 false
when "i" is exactly -1.
Note that ~
always 3 coerces its operand to integer; that is, it 2 forces non-integer floating point values 1 to integer, as well as non-numeric values.
You're right: This code will return false
when 3 the indexOf
call returns -1; otherwise true
.
As you 2 say, it would be much more sensible to use 1 something like
return this.modifiedPaths.indexOf(path) !== -1;
The ~
operator is the bitwise NOT operator. What 5 this means is that it takes a number in 4 binary form and turns all zeroes into ones 3 and ones into zeroes.
For instance, the number 2 0 in binary is 0000000
, while -1 is 11111111
. Likewise, 1 1 is 00000001
in binary, while -2 is 11111110
.
My guess is that it is there because it's 9 a few characters shorter (which library 8 authors are always after). It also uses 7 operations that only take a few machine 6 cycles when compiled into the native code 5 (as opposed to the comparison to a number.)
I 4 agree with another answer that it's an overkill 3 but perhaps might make sense in a tight 2 loop (requires performance gain estimation, though, otherwise 1 may turn out to be premature optimization.)
I assume, since it is a bitwise operation, it 2 is the fastest (computationally cheap) way 1 to check whether path appears in modifiedPaths.
As (~(-1)) === 0
, so:
!!(~(-1)) === Boolean(~(-1)) === Boolean(0) === false
0
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.