While writing a swap function using chained shorthand operators in javascript, I stumbled upon something which puzzled me a lot.
This code is supposed to swap a and b values.
var a = 4532;
var b = 969;
a^=b^=a^=b;
But it doesn't: b = 4532, but a = 0.
If I break this code in 2 lines, it works as intended.
var a = 4532;
var b = 969;
b^=a^=b;
a^=b;
What is the technical explanation?
PS: here's the code on jsfiddle if someone wants to quickly try for himself.
Before answering your question, can you tell the result of the following code?
var c = 1;
c += c += 1;
You may believe that it's 4, try it yourself :)
I have no idea of how the javascript code is interpreted under the hood. Here is how I try to explain why that happened.
By a += b
, it is equal to a = a + b
. So, c += c += 1
is c = c + (c = c + 1)
. Assignment in form of (c + (c = c + 1))
, the result is (c + c + 1)
. Here I think it is the key point, and it's confusing, the variable c
is still 1
, although we reassign a new value c + 1
to it, in the first assignment c += 1
.
So, a^=b^=a^=b
is equal to a = a^b^a^b
, that's 0
. Because the internal change to a
is ignored, or maybe it's a bug?
My another guess is that, the code may be expanded like this:
c = 1 + (c = 1 + 1)// in form of c = c + (c = c + 1)
That's all my guesses, cause I don't know how the bytecode generated by VM looks like. Hopes it is useful.