Question

Let's evaluate this code for swapping two variables :

var a = 5, b = 3; 
a = ( a -( b = ( a = a+b ) - b ) );

I was expecting that new value of a should be 3 and value of b should be 5. But I got values as a = 0 and b = 5;

I went and read the EcmaScript Arithmetic expression and found that this will be evaluated from left-to-right. ( but not completely clear ).

So I tried this one

var a = 5, b = 3; 
a = ( ( b = ( a = a+b ) - b ) - a );

Now I got a = -3 and b = 5. Can somebody explain me why this is happening like this ?

Était-ce utile?

La solution 2

As you said, the expression is evaluated from left to right, meaning the first time a is encountered, its value is still 5. This comes down to:

var a = 5, b = 3; 
a = ( a -( b = ( a = a+b ) - b ) );
a = 5 - (b = (a=(5+3)) - b);
a = 5 - (b = 8 - b);
a = 5 - 5; AND b = 5

In the second one, the a value is evaluated after the assignment because it is on the right

var a = 5, b = 3;
a = ( ( b = ( a = a+b ) - b ) - a );
a = ( ( b = 8 - b ) - a ); AND a = 8
a = ( 5 - 8 ); AND a = 8; AND b = 5;
a = - 3;

It all comes down to the order of the evaluation of the operands.

Typically in the first case, a is evaluated to 5, then b = ( a = a+b ) - b is evaluated, and only during this evaluation the value of a changes, but is not backported.

In the second example, ( b = ( a = a+b ) - b ) is evaluated first, changing the a value to 8, then a is evaluated, and is found to be 8

A more trivial example is :

var a = 5
a = a + (a = 2)
// a = 7

a is evaluated to 5, then (a = 2) is evaluated to 2 and a is set to 2, then 5+2 is evaluated and a is set to 7.

On the other hand :

var a = 5
a = (a = 2) + a
// a = 4

(a = 2) is evaluated to 2 and a is set to 2, then a is evaluated to 2, then 2+2 is evaluated and a is set to 4

Autres conseils

Here is the explanation, I hope it is clear because it is not so obvious. JS and all other languages create a tree to evaluate expressions. The tree assigns a weight to each operator depending on their position and on the braces.

First, here is the steps JS would process the expression:

Step 0. a = ( a - ( b = ( a = a+b ) - b ) );   a=5, b=3
Step 1.                   a = a+b              a=8, b=3
Step 2.             b = a - b                  a=8, b=5 
Step 3. a = a - b                              a=0, b=5

At each step it processes one operator.

And this is the tree it creates from you expression:

    =
  /   \
 a     - 
     /    \
   a       =
          /  \   
         b    -            
             / \
            =   b
           /  \
          a    +
              / \
             a   b

The tree is then processed from bottom to top.

var a = 5, b = 3;
a = ( ( b = ( a = a+b ) - b ) - a );

It will operate in this way.

a = a + b //8
b = a - b //8-3=5
a = b - a //5-8=-3
var a = 5, b = 3; 
a = ( a -( b = ( a = a+b ) - b ) );

1) a = a(5) - (rest of expression, where 2 parts will be calculated soon)

2) b = (a = a+b // and it's still not calculated) - b (which is 3, because new b is not changed yet)

3) a = 5(a) + 3(b) = 8

4) b(we are back to point 2) = 8(new a) - 3(old b) = 5

5) a(point 1) = 5(old a) - 5(new b) = 0

New a = 0, new b = 5

var a = 5, b = 3; 
a = ( ( b = ( a = a+b ) - b ) - a );

1) b = ( a = a+b ) - 3(b)

2) a = 5(a) + 3(b) = 8

3) b = 8(new a) - 3(old b) = 5

4) a(final) = 5(new b) - 8(new a) = -3

New a = -3, new b = 5

I hope it's readable :D

a = ( a -( b = ( a = a+b ) - b ) ) 

is similar to this

a = ( 5 -( b = ( a = 5+3 ) - 3 ) ) // a = 8
// a = ( 5 - ( b = 8 - 3 ) ) // b = 5
// a = ( 5 - 5 ) // a = 0

meaning it will replace a and b on the left side of = in one go with the same initial values, it's not similar to this sequence

a = a+b; // a = 8
b = a-b; // b = 5
a = a-b; // a = 3

as you expect.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top