Can (a== 1 && a ==2 && a==3) ever evaluate to true?

2540

Moderator note: Please resist the urge to edit the code or remove this notice. The pattern of whitespace may be part of the question and therefore should not be tampered with unnecessarily. If you are in the "whitespace is insignificant" camp, you should be able to accept the code as is.

Is it ever possible that (a== 1 && a ==2 && a==3) could evaluate to true in JavaScript?

This is an interview question asked by a major tech company. It happened two weeks back, but I'm still trying to find the answer. I know we never write such code in our day-to-day job, but I'm curious.

This question is tagged with javascript ecmascript-6

~ Asked on 2018-01-15 20:20:47

The Best Answer is


3374

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.

_x000D_
_x000D_
const a = {_x000D_
  i: 1,_x000D_
  toString: function () {_x000D_
    return a.i++;_x000D_
  }_x000D_
}_x000D_
_x000D_
if(a == 1 && a == 2 && a == 3) {_x000D_
  console.log('Hello World!');_x000D_
}
_x000D_
_x000D_
_x000D_


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.

~ Answered on 2018-01-15 20:35:15


2076

I couldn't resist - the other answers are undoubtedly true, but you really can't walk past the following code:

_x000D_
_x000D_
var a? = 1;_x000D_
var a = 2;_x000D_
var ?a = 3;_x000D_
if(a?==1 && a== 2 &&?a==3) {_x000D_
    console.log("Why hello there!")_x000D_
}
_x000D_
_x000D_
_x000D_

Note the weird spacing in the if statement (that I copied from your question). It is the half-width Hangul (that's Korean for those not familiar) which is an Unicode space character that is not interpreted by ECMA script as a space character - this means that it is a valid character for an identifier. Therefore there are three completely different variables, one with the Hangul after the a, one with it before and the last one with just a. Replacing the space with _ for readability, the same code would look like this:

_x000D_
_x000D_
var a_ = 1;_x000D_
var a = 2;_x000D_
var _a = 3;_x000D_
if(a_==1 && a== 2 &&_a==3) {_x000D_
    console.log("Why hello there!")_x000D_
}
_x000D_
_x000D_
_x000D_

Check out the validation on Mathias' variable name validator. If that weird spacing was actually included in their question, I feel sure that it's a hint for this kind of answer.

Don't do this. Seriously.

Edit: It has come to my attention that (although not allowed to start a variable) the Zero-width joiner and Zero-width non-joiner characters are also permitted in variable names - see Obfuscating JavaScript with zero-width characters - pros and cons?.

This would look like the following:

_x000D_
_x000D_
var a= 1;_x000D_
var a?= 2; //one zero-width character_x000D_
var a??= 3; //two zero-width characters (or you can use the other one)_x000D_
if(a==1&&a?==2&&a??==3) {_x000D_
    console.log("Why hello there!")_x000D_
}
_x000D_
_x000D_
_x000D_

~ Answered on 2018-01-16 05:14:54


Most Viewed Questions: