Can a construct (a == 1 && a == 2 && a == 3) be true in JavaScript?
- Transfer
Recently, an interesting piece of JavaScript code walked on Twitter and Reddit . The question associated with him was: "Can the expression be

Here he is:
If you use Google Chrome, open the developer tool console using the keyboard shortcut
In fact, there is nothing surprising here. This code simply uses two basic JavaScript concepts:
Note that in the expression under study
In JavaScript there is a built-in method to convert an object to a primitive value:
Create an object:
As stated above, when we call
In addition, we can use
The most interesting thing when working with
Here we have replaced the standard method
All this leads to the following:
Apparently, now
Now let's talk about why this is important.
When calculating the result of a non-strict equality operation for operands of various types, JavaScript will try to cast types - that is, it will try to cast (convert) the operands to similar types or to the same type.
In our expression
Since we changed the standard method
Is the problem solved? Not yet, but nothing left.
Now we need a way to systematically increase the value
This operator simply adds the value of the right operand to the variable that is on the left, and assigns the resulting value to this variable. Here is a simple example:
As you can see, every time we use the assignment operator with addition, the value of the variable increases! We use this idea in our method
Instead of just returning
After this change is made to the code, we can finally try everything:
Works!
Remember that when using the lax equality operator, JS tries to perform type conversion. Our object calls a method
It may be useful to consider what is happening step by step:
We believe that examples like the one discussed above help, firstly, to better learn the basic features of JavaScript, and secondly, they do not forget that in JS, not everything is what it seems.
Dear readers! If you know about any oddities from the field of JavaScript - please share them.

(a==1 && a==2 && a==3)returned true?" The answer to the question, oddly enough, was positive.
Today we will analyze this code and try to understand it.
Here he is:
const a = {
num: 0,
valueOf: function() {
returnthis.num += 1
}
};
const equality = (a==1 && a==2 && a==3);
console.log(equality); // trueIf you use Google Chrome, open the developer tool console using the keyboard shortcut
Ctrl + Shift + Jon Windows or Cmd + Opt + JmacOS. Copy this code, paste it into the console and make sure that the output really works true.What is the catch?
In fact, there is nothing surprising here. This code simply uses two basic JavaScript concepts:
- The operator of lax equality.
- Object method
valueOf().
Strict Equality Operator
Note that in the expression under study
(a==1 && a==2 && a==3),, the non-strict equality operator is used. This means that during the calculation of the value of this expression type casting will be used, that is, with the help of ==it you can compare the values of different types. I already wrote a lot about this, so I will not go into details here. If you need to recall the features of the comparison operators in JS - refer to this material .ValueOf () method
In JavaScript there is a built-in method to convert an object to a primitive value:
Object.prototype.valueOf(). By default, this method returns the object for which it was called. Create an object:
const a = {
num: 0
}As stated above, when we call
valueOf()for an object a, it simply returns the object itself:a.valueOf();
// {num: 0}In addition, we can use
typeOf()to check whether the valueOf()object actually returns:typeof a.valueOf();
// "object"We write our valueOf ()
The most interesting thing when working with
valueOf()is that we can override this method in order to convert an object into a primitive value with it. In other words, it can be used valueOf()to return strings, numbers, booleans, and so on instead of objects. Take a look at the following code:a.valueOf = function(){
returnthis.num;
}Here we have replaced the standard method
valueOf()for the object a. Now the call valueOf()returns a value a.num. All this leads to the following:
a.valueOf();
// 0Apparently, now
valueOf()returns 0! The most important thing here is that 0 is the value that is assigned to the property of the object a.num. We can verify this by performing several tests:typeof a.valueOf();
// "number"
a.num == a.valueOf()
// trueNow let's talk about why this is important.
Non-Strict Equality Operation and Type Casting
When calculating the result of a non-strict equality operation for operands of various types, JavaScript will try to cast types - that is, it will try to cast (convert) the operands to similar types or to the same type.
In our expression
(a==1 && a==2 && a==3),, JavaScript will try to cast the object ato a number type before comparing it to a number. When performing a cast operation on a JavaScript object, it will first try to call the method valueOf(). Since we changed the standard method
valueOf()so that now it returns a value a.numthat is a number, now we can do the following:a == 0
// trueIs the problem solved? Not yet, but nothing left.
Assignment Operator with Addition
Now we need a way to systematically increase the value
a.numeach time it is called valueOf(). Fortunately, JavaScript has an assignment operator with addition, or an additional assignment operator ( +=). This operator simply adds the value of the right operand to the variable that is on the left, and assigns the resulting value to this variable. Here is a simple example:
let b = 1console.log(b+=1); // 2console.log(b+=1); // 3console.log(b+=1); // 4As you can see, every time we use the assignment operator with addition, the value of the variable increases! We use this idea in our method
valueOf():a.valueOf = function(){
returnthis.num += 1;
}Instead of just returning
this.num, we will now, with each call valueOf(), return a value this.numincreased by 1 and write the new value to this.num. After this change is made to the code, we can finally try everything:
const equality = (a==1 && a==2 && a==3);
console.log(equality); // trueWorks!
Step by step analysis
Remember that when using the lax equality operator, JS tries to perform type conversion. Our object calls a method
valueOf()that returns a.num += 1, in other words, returns a value a.numincreased by one each time it is called. Now it remains only to compare two numbers. In our case, all comparisons will produce true. It may be useful to consider what is happening step by step:
a == 1 ->
a.valueOf() == 1 ->
a.num += 1 == 1 ->
0 += 1 == 1 ->
1 == 1 -> true
a == 2 ->
a.valueOf() == 2 ->
a.num += 1 == 2 ->
1 += 1 == 2 ->
2 == 2 -> true
a == 3 ->
a.valueOf() == 3 ->
a.num += 1 == 3 ->
2 += 1 == 3 ->
3 == 3 -> trueSummary
We believe that examples like the one discussed above help, firstly, to better learn the basic features of JavaScript, and secondly, they do not forget that in JS, not everything is what it seems.
Dear readers! If you know about any oddities from the field of JavaScript - please share them.
