Some of javascript's more esoteric operators:
Bitwise NOT: ~
The bitwise "not"-operator has some pretty weird but interesting side effects. Its basic functions on numbers can be described as:
~N = -(N+1)
Now, the way you see this operator used is more often than not for flooring numbers:
~~10.23342 // returns 10
The reason this works is because all bitwise operations are performed on 32-bit integers in javascript:
~10.23342 // => -11 (Rounded when converted to integer) ~-11 // => 10 (-(-11+1) = 10)
Taking this one step further, this can be used to convert -1 to false. Functions like Array.indexOf, String.indexOf and String.search returns -1 on "not found".
var facon = "sundriedtomatoesisvegetarianbacon";
if(~facon.search("bacon")) eat(facon);
// HAHA! tricking meat eaters into eating vegetarian@webreflection Has written much better about the javascript tilde trick, and it's also mentioned by Dreaming Javascript
Bit-shifting ( >>, >>>, << )
One possible use-case for bitshifting in javascript is when working with hex colors, for example can we use bit-shifting to filter out Red, Green and Blue values:
Filtering out hex values:
111111111111111111111111
32-bit (16 777 215 in Base 10)
R G B
11111111 11111111 11111111
Mask for filtering G-value:
00000000 11111111 00000000
Combine with bitwise & (Only saving the spots where BOTH numbers are 1)
Example: Base-10 color-value: 16737792 – the orange color in the "Hacker News"-logo
00000000 11111111 00000000 // Mask
&
11111111 01100110 00000000 // Color value
=
00000000 01100110 00000000 // result => 26112
Bit shift it to get only the "green"-value:
26112 >> 8 => 102 // removing the lowest (rightmost) 8 bitsRaphael.js uses bitshifting for the reverse operation, converting an object like { R: 10, G: 20, B: 255 } into a hex value:
rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);
(Line 855, Raphael.js)
The bit-operator part is: (16777216 | blue | (green << 8) | (red << 16))
Dimitry is using the | (and/or) operator to add up a hex number:
So let look at this:
First we create a mask, that we add the numbers to: in base(2) 1000000000000000000000000. This is one number bigger than the highest RGB-color value on Base(10). We'll soon see why.
The "blue" value is a normal color-value, for example 255:
16777216 | 255 means:
1 00000000 00000000 00000000
| (inclusive or)
0 00000000 00000000 11111111
=
1 00000000 00000000 11111111
The green value needs to be shifted 8 bits to the left: 66
66 << 8 => 16896
1 00000000 00000000 11111111 // number after adding blue value:
|
0 00000000 01000010 00000000
=
1 00000000 01000010 11111111
(And the same thing repeated with the red color, that needs to be shifted 16 bits.)
Red Green Blue
1 01100100 01000010 11111111
This number is now converted to Hex with (number).toString(16):
(parseInt("1011001000100001011111111", 2)).toString(16)
// we need to convert out binary number to Base 10 first, hence parseInt
Now we'll delete out initially added "1 time bigger" number:
(parseInt("1011001000100001011111111", 2)).toString(16).slice(1)
And add a # to the start, then we'll have a hex number.Bit-shifting is extensively used in Mozilla's pdf.js and also appears in Mr Doob's Three.js. I'm sure it's relevant in those extremely performance-heavy use-cases, because when you start creeping up towards tens of millions of loops per second, the difference between shift-right 2 bits and divide by four (which is the same operation on integers) starts to make sense