If you take advantage of how ==
works, you could simply create an object with a custom toString
(or valueOf
) function that changes what it returns each time it is used such that it satisfies all three conditions.
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
The reason this works is due to the use of the loose equality operator. When using loose equality, if one of the operands is of a different type than the other, the engine will attempt to convert one to the other. In the case of an object on the left and a number on the right, it will attempt to convert the object to a number by first calling valueOf
if it is callable, and failing that, it will call toString
. I used toString
in this case simply because it’s what came to mind, valueOf
would make more sense. If I instead returned a string from toString
, the engine would have then attempted to convert the string to a number giving us the same end result, though with a slightly longer path.