Recently, this question has been making the round on different sites on the internet like Reddit and StackOverflow.
The answer to the question is Yes!, it is possible in JavaScript.
You might have already seen the solution on different sites, I will try to explain the code to make you understand why it works.
const a = { i: 1, valueOf: function () { return a.i++; } } if(a == 1 && a == 2 && a == 3) { console.log('JavaScript Rocks!'); }
Why It Works?
There isn't any trick in this code. The solution is simply using the concept of loose equality using double equals(==) operator. If you need to understand the difference between double equals vs triple equals, please read my this article. JavaScript Triple Equals Operator vs Double Equals Operator ( === vs == )
If you have noticed, we compared two different types here in a == 1. Here a is an object which is compared to a number. Whenever we compare two different types with a double equal operator, type coercion happens. In type coercion, operator tries to convert both types to a similar type.
In this case, the object will be converted to primitive(number) type by calling the function valueOf if it is available.
valueOf is a builtin function in JavaScript to convert an object to a primitive type, if no primitive value available in the object, valueOf returns the object itself. If valueOf fails then toString is used to convert an object to a string. In toString case, the number on the right-hand side will also be converted to a string for comparison using loose equality(==) operator.
The cool thing is that these methods valueOf and toString can be overwritten.
a.valueOf = function() { return 'magic will happen here!'; }
Here we have overwritten the native implementation of the valueOf function with our own. As we know while doing a comparison with double equals operator, it coerces the object type to a primitive type by invoking the valueOf function of the object type.
The Magic Spell
To evaluate (a ==1 && a== 2 && a==3) this statement to true, we need to increment the value of a systematically. To achieve this we have overwritten the valueOf the object as:
valueOf: function () { return a.i++; }
We have initialized the i with 1 and then incremented it using ++ operator after each use. So our expression (a ==1 && a== 2 && a==3) will be break into following steps:
- While comparing a == 1; valueOf function of the object will return current value of i(which is 1) and after returning the value will increment it to 2
- While comparing a == 2; valueOf function of the object will return current value of i(which is now 2) and after returning the value will increment it to 3
- While comparing a == 3; valueOf function of the object will return current value of i(which is now 3) and after returning the value will be incremented to 4
Hope this article helped you to understand it. If you have any question please post it in comments.
Lol, it's possible in a lot of languages, that's how they work...
ReplyDeleteNice post. I really enjoy reading it. Very instructive, keep on writing.
ReplyDelete