a = a++ does not increment a

Sakshi Shreya
5 min readSep 20, 2019

I was talking to a friend today and I just happened to ask a very common but tricky question as a challenge. He gave me the answer to the problem but in return, we were left with a new problem…

INPUT:
a = 1;
a = a++;
console.log(a);
OUTPUT:
1
EXPECTED OUTPUT:
2

Why is 2 expected?

Let’s do it step by step (by the way the answer is 1 for C, C++, Java, JavaScript and other languages also that support postfix operators).

Step 1: a = 1;

Here 1 is assigned to a. This part is very clear.

Step 2: a = a++;

There can be two approaches here.

Approach 1: First value of a is assigned to a and then incremented.

This was my first thought.

a = 1 right now. When the old value of a is assigned back to a, the new value becomes 1.

Then a gets incremented. So, a should be 2.

After talking to a lot of people about this problem, I noticed one common notion here. People tend to forget that a++ or ++a do the same thing to a. That is, a++ or ++a has the same effect as a = a + 1 for a (we are considering no other function or variable).

For e.g.

INPUT:
a = 1;
b = a++;
console.log(a, b);
OUTPUT:
2 1
EXPECTED OUTPUT:
2 1

Here we can see that first the value got assigned to b. That is why its value is 1. Then a was incremented which makes its value 2. This is right and expected. But what happens when we do a = a++; ?

Approach 2: First value of a is incremented and then the new value is assigned.

The second thought led me to search for precedence order.

Here, postfix and prefix increment/decrement operators (++/--)are above assignment operator (=). That is true for every other language but I thought, maybe increment happens first and then assignment (which is logically wrong).

But in this case also, first a gets incremented to 2. Then the new value gets assigned which is 2.

This is not a solution.

Hey! but our minds are created in such a way that if we find out that what the solution is, we reverse engineer our way to that solution even if we are not satisfied with it.

What I reverse engineered…

My solution, in this case, was: (Don’t judge me on reading this. You will get to know why.)

Maybe it happens like this:

First, since postfix operator has higher precedence it operates first. It increments the value of a and stores the value internally. (Because the incremented value is not going to be used first. Before increment, the assignment has to take place). So, internally a = 2, but this value is not available outside.

Second, the assignment takes place. Since a still contains the old value, the old value is assigned to a. Now a becomes 1.

Third, the internal value of a has to be assigned to a now. But the internal value is lost. So, it was again set to 1.

That was my mind working out solutions. But this is not completely wrong.

The actual answer…

The third thought led me to read the standard (this is a tough task). As per the ECMAScript standard, section 11.3.1:

JavaScript is a functional programming language. This means all operations are functions only. The algorithm for postfix increment is written as:

1. Let lhs be the result of evaluating LeftHandSideExpression.
2. Throw a SyntaxError exception if the following conditions are all true:
2.1. Type(lhs) is Reference is true
2.2. IsStrictReference(lhs) is true
2.3. Type(GetBase(lhs)) is Environment Record
2.4. GetReferencedName(lhs) is either "eval" or "arguments"
3. Let oldValue be ToNumber(GetValue(lhs)).
4. Let newValue be the result of adding the value 1 to oldValue, using the same rules as for the + operator (see 11.6.3).
5. Call PutValue(lhs, newValue).
6. Return oldValue.

Overwhelmed? No worries… I am here to explain.

Step 1: A variable lhs is declared. This is the memory location of the variable to be incremented. lhs is memory location of the variable a in our case.

Step 2: Some conditions are checked and if all of them are true then, the variable won’t be able to increment. Thus, an error is thrown. These conditions are: whether the lhs is of type reference or strict reference, whether its base type is ‘Environment Record’, whether it is eval or arguments type. Blah blah blah…

Step 3: We know, in JS, coercion plays a very important role. This step is doing just that. It gets the value from the variable. Converts it to the number type and stores in oldValueoldValue = 1

Step 4: 1 is added to oldValue and stored in newValuenewValue = oldValue + 1newValue = 2

Step 5: PutValue function is called. This function in itself is complex but in short, it updates the value in newValue to the variable stored at lhs. At this moment, a becomes 2. Don’t be happy just yet. Some steps are still left.

Step 6: The oldValue is returned (coz you know, it is a postfix operator. The previous value of a has to be used in this statement). So, 1 is returned.

This is what a++ does. This looks pretty easy. And now you know why I told you to not judge me. I was very close.

CASE 1

INPUT:
a = 1;
console.log(a++);
console.log(a);
OUTPUT:
1
2
EXPECTED OUTPUT:
1
2

This is because a was incremented internally in line-2. Thus a = 2, but 1 was returned which is printed.

CASE 2

INPUT:
a = 1;
b = a++;
console.log(a, b);
OUTPUT:
2 1
EXPECTED OUTPUT:
2 1

This is because a was incremented internally in line-2. Thus a = 2, but 1 was returned which is stored in b.

CASE 3

INPUT:
a = 1;
a = a++;
console.log(a);
OUTPUT:
1
EXPECTED OUTPUT:
1

This is because a was incremented internally in RHS of line-2. Thus a = 2, but 1 was returned which is stored back in a. So, a becomes 1 again.

So, that was yet another solution to a tricky JS problem that I encountered during my work. These kinds of problems lead me to dig into the standards that are set, which we blindly follow without knowing what is happening internally. I hope this issue was properly explained. If you liked the blog, do not forget to ‘clap’.

You can find me on these links:

LinkedIn: https://www.linkedin.com/in/sakshishreya/

Twitter: https://twitter.com/shreyasakshi96

Github: https://github.com/SakshiShreya/

Credits:

Credits for this blog goes to that mad friend who helped me find the topic — Hitesh Goel.

You can find him on this link:

Linkedin: https://www.linkedin.com/in/hitesh-goel-76703b10b

--

--