What Do These JavaScript Bitwise Operators Do

What do these JavaScript bitwise operators do?

<<, >>

Bit shift left and right, respectively. If you imagine the left operand as a binary sequence of bits, you are shifting those to the left or right by the number of bits indicated by the right operand.

&, ^, |

These are bitwise and, xor, and or, respectively. You can think of & and | as the counterparts to && and ||, except that they will treat their operands as bit vectors, and perform the logical operations on each of the bits. There is no ^^ operator, but this operation is "xor" or "exclusive or". You can think of "a xor b" as "a or b, but not both".

What is the different of bitwise operation between javascript and java

In javascript, you can perform bitwise operations on 32-bit numbers only. Even javascript use IEEE 754 floating-point standard to represent the number. Bitwise operation can be performed on 32-bit number. Hence rest of the bits will get ignored.

To convert any number to its 32-bit representation, number | 0 with it. When javascript reads x & y it considers 32-bits of x and y and ignores other bits silently. In your case, the numbers on which you are performing bitwise are x = -271733879 and y = -1732584194.

The safe range for bitwise operations in Javascript is Math.pow(-2,31) (-2147483648, about -2.1 billion) to Math.pow(2,32)-1 (2147483647, about +2.1 billion).

x= 4023233417;console.log(x.toString(2))y = 2562383102 ;console.log(y.toString(2));
result = x & y;
console.log(result.toString(2)); //-1110111011101110111011101111000
x = x | 0; //-271733879y = y | 0; //-1732584194console.log("32 bit x: " + x);console.log("32 bit y: " + y);result = x & y;
console.log(result.toString(2)); //-1110111011101110111011101111000

Javascript bitwise operators - explanation required

First statement has almost nothing to do with bitwise operators.
It simply means:

  • assign random number between 0 and 15 to r, but if variable d is undefined, give me 0. It uses math fact that modulo 16 of any number gives you a result in [0..15] range and bitwise OR with 0 is an identity operation with one exception. JavaScript logic of handling undefined dictates that without | 0 when d is undefined you will get NaN as a result in r.

Second statement does use bitwise operators.

  • x & 0x03 is the same as x BITWISE_AND 0011 and it returns lowest 2 bits of x. x | 0x8 always sets 4th bit. So, c will be a 10.. where dots are the lowest 2 bits of r. Of course, it will happen only if c is a string and equals x.

I strongly suggest you read https://www.w3schools.com/js/js_bitwise.asp and do some experimentation.

What are bitwise operators?

Since nobody has broached the subject of why these are useful:

I use bitwise operations a lot when working with flags. For example, if you want to pass a series of flags to an operation (say, File.Open(), with Read mode and Write mode both enabled), you could pass them as a single value. This is accomplished by assigning each possible flag it's own bit in a bitset (byte, short, int, or long). For example:

 Read: 00000001
Write: 00000010

So if you want to pass read AND write, you would pass (READ | WRITE) which then combines the two into

00000011

Which then can be decrypted on the other end like:

if ((flag & Read) != 0) { //...

which checks

00000011 &
00000001

which returns

00000001

which is not 0, so the flag does specify READ.

You can use XOR to toggle various bits. I've used this when using a flag to specify directional inputs (Up, Down, Left, Right). For example, if a sprite is moving horizontally, and I want it to turn around:

     Up: 00000001
Down: 00000010
Left: 00000100
Right: 00001000
Current: 00000100

I simply XOR the current value with (LEFT | RIGHT) which will turn LEFT off and RIGHT on, in this case.

Bit Shifting is useful in several cases.

x << y

is the same as

x * 2y

if you need to quickly multiply by a power of two, but watch out for shifting a 1-bit into the top bit - this makes the number negative unless it's unsigned. It's also useful when dealing with different sizes of data. For example, reading an integer from four bytes:

int val = (A << 24) | (B << 16) | (C << 8) | D;

Assuming that A is the most-significant byte and D the least. It would end up as:

A = 01000000
B = 00000101
C = 00101011
D = 11100011
val = 01000000 00000101 00101011 11100011

Colors are often stored this way (with the most significant byte either ignored or used as Alpha):

A = 255 = 11111111
R = 21 = 00010101
G = 255 = 11111111
B = 0 = 00000000
Color = 11111111 00010101 11111111 00000000

To find the values again, just shift the bits to the right until it's at the bottom, then mask off the remaining higher-order bits:

Int Alpha = Color >> 24
Int Red = Color >> 16 & 0xFF
Int Green = Color >> 8 & 0xFF
Int Blue = Color & 0xFF

0xFF is the same as 11111111. So essentially, for Red, you would be doing this:

Color >> 16 = (filled in 00000000 00000000)11111111 00010101  (removed 11111111 00000000)
00000000 00000000 11111111 00010101 &
00000000 00000000 00000000 11111111 =
00000000 00000000 00000000 00010101 (The original value)

what does ^= mean in js

Bitwise XOR assignment (^=)

The bitwise XOR assignment operator (^=) uses the binary representation of both operands, does a bitwise XOR operation on them and assigns the result to the variable.

Source: MDN

~ bitwise operator in JavaScript

Under the covers, when Javascript does bitwise operations, it converts to a 32-bit signed integer representation, and uses that, then converts the result back into its internal decimal representation.

As such, your input value, 010001 becomes 00000000 00000000 00000000 00010001.

This is then inverted:

~00000000 00000000 00000000 00010001 => 11111111 11111111 11111111 11101110

Converted into hex, the inverted value is 0xFFFFFFEE, which is equivalent to the decimal value of -18.

Since this is a signed integer with a value of -18, this value is converted to the underlying decimal representation of -18 by Javascript.

When Javascript tries to print it as a base-2 number, it sees the negative sign and the value of 18, and prints it as -10010, since 10010 is the binary representation of positive 18.

What does 'x ~y' represent in JavaScript?

x << -n is equal to x << (32 - n)
~3 == -4 so

5 << ~3 === 5 << (32 - 4) === 5 << 28 which is 1,342,177,280

to be accurate X << -n is not the same as X << (32 - n) ... in fact it's both simpler and more complicated ... the valid range of a bit shift operator is 0 to 31 ... the RHS in a bit shift operator is first converted to an unsigned 32 bit integer, then masked with 31 (hex 1f) (binary 11111)

                   3 = 00000000000000000000000000000011  
~3 = 11111111111111111111111111111100
0x1f (the mask) 00000000000000000000000000011111
--------------------------------
~3 & 0x1f 00000000000000000000000000011100 = 28

when the magnitude is less than 32, it's exactly the same as what I posted above though

Bit operations work with 32 bit integers. Negative bit shifts are meaningless so are wrapped into positive 32 bit integers

How the << operator works

The rhs is converted to an unsigned 32bit integer - like explained here ToUInt32

ToUint32 basically takes a number and returns the number modulo 2^32

How does bitwise-and operator work on objects in javascript?

The intent of the deep variable is to detect the difference between these two calls:

Extend({keyA: {a: 1}, keyB: 2}, {keyC: 3, keyA: {b: 2}});

and

Extend(true, {keyA: {a: 1}, keyB: 2}, {keyC: 3, keyA: {b: 2}});

The first variant will return this:

{keyA: {b: 2}, keyB: 2, keyC: 3}

The second is intended to return this:

{keyA: {a: 1, b: 2}, keyB: 2, keyC: 3}

So the function in fact allows for a first, optional argument, that will make the function apply the extension recursively so you get a deep instead of a shallow extended object.
You can also see this intent by analysing the recursive call, where the first argument is deep, the second is the object to extend, and the third the object to extend with.
The following line also shows this:

var i = 1 + deep;

As i is point where the loop will start from, you can see that if deep is set to 1 instead of 0, the loop will start processing from argument #2 onwards, which makes sense, as argument #0 was recognised as being the optional argument, and the next one is the target object.
Note that the function accepts a variable number of additional arguments which it will use to extend the target object with. It is over these arguments that the i variable loops.

As a side note: because of a bug, the second version returns the same as the first. To fix the bug, replace

target[propName] = (deep && IsPlainObject(target[propName]))
? Extend(deep, {}, propValue) : propValue;

with:

target[propName] = (deep && IsPlainObject(target[propName]))
? Extend(deep, target[propName], propValue) : propValue;

Now, coming to the essence:

var deep = 1 & args[0];

The use of the bitwise operator must have been an idea to have efficiency rule over clarity. The intent was to set deep to 1 if the first argument represented the optional argument, which should be a boolean indicating whether the extending should happen shallow or deep. As objects will make this expression evaluate to 0, it seemed like a nice trick.
But there is an issue with this. If one would like to do this:

Extend(["3"], {myattr: 2});

One would expect to get back an array-like object with an additional custom property myattr:

{0: "3", length: 1, myattr: 2}

However, the current Extend function will misinterpret the first argument as an instruction to perform a deep extension. This is because
1 & ["3"] will evaluate to 1 & 3, which evaluates to 1. And so the result will be the second argument without any extension happening:

{myattr: 2}

Conclusion: it is better to avoid such cryptic use of bitwise operators, and do something like this:

var deep = args.length > 0 && typeof args[0] === 'boolean' && args[0];

In common language: let deep be true (1) when there is at least one argument and that argument is a boolean and its value is true. In all other cases let it be false (0).
Note that one cannot pass false as the first argument, thinking that it will make the function perform a shallow extension. In this case,
that argument will be taken as the object to extend, which will fail. So the optional first argument, if provided, must be a boolean with value true.
This is true both for the original Extend function and the corrected one.

Finally, it would be good to add comments to this function to clarify the use of the first optional argument.



Related Topics



Leave a reply



Submit