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.
JavaScript
a == a +1
In JavaScript, there are no integers but only
Number
s, which are implemented as double precision floating point numbers.It means that if a Number
a
is large enough, it can be considered equal to three consecutive integers:True, it's not exactly what the interviewer asked (it doesn't work with
a=0
), but it doesn't involve any trick with hidden functions or operator overloading.Other languages
For reference, there are
a==1 && a==2 && a==3
solutions in Ruby and Python. With a slight modification, it's also possible in Java.Ruby
With a custom
==
:Or an increasing
a
:Python
Java
It's possible to modify Java
Integer
cache:If you ever get such an interview question (or notice some equally unexpected behavior in your code) think about what kind of things could possibly cause a behavior that looks impossible at first glance:
Encoding: In this case the variable you are looking at is not the one you think it is. This can happen if you intentionally mess around with Unicode using homoglyphs or space characters to make the name of a variable look like another one, but encoding issues can also be introduced accidentally, e.g. when copying & pasting code from the Web that contains unexpected Unicode code points (e.g. because a content management system did some "auto-formatting" such as replacing
fl
with Unicode 'LATIN SMALL LIGATURE FL' (U+FB02)).Race conditions: A race-condition might occur, i.e. a situation where code is not executing in the sequence expected by the developer. Race conditions often happen in multi-threaded code, but multiple threads are not a requirement for race conditions to be possible – asynchronicity is sufficient (and don't get confused, async does not mean multiple threads are used under the hood).
Note that therefore JavaScript is also not free from race conditions just because it is single-threaded. See here for a simple single-threaded – but async – example. In the context of an single statement the race condition however would be rather hard to hit in JavaScript.
JavaScript with web workers is a bit different, as you can have multiple threads. @mehulmpt has shown us a great proof-of-concept using web workers.
Side-effects: A side-effect of the equality comparison operation (which doesn't have to be as obvious as in the examples here, often side-effects are very subtle).
These kind of issues can appear in many programming languages, not only JavaScript, so we aren't seeing one of the classical JavaScript WTFs here1.
Of course, the interview question and the samples here all look very contrived. But they are a good reminder that:
1 For example, you can find an example in a totally different programming language (C#) exhibiting a side-effect (an obvious one) here.
Here's another variation, using an array to pop off whatever values you want.
Alternatively, you could use a class for it and an instance for the check.
EDIT
Using ES6 classes it would look like this
This is possible in case of variable
a
being accessed by, say 2 web workers through a SharedArrayBuffer as well as some main script. The possibility is low, but it is possible that when the code is compiled to machine code, the web workers update the variablea
just in time so the conditionsa==1
,a==2
anda==3
are satisfied.This can be an example of race condition in multi-threaded environment provided by web workers and SharedArrayBuffer in JavaScript.
Here is the basic implementation of above:
main.js
worker.js
modifier.js
On my MacBook Air, it happens after around 10 billion iterations on the first attempt:
Second attempt:
As I said, the chances will be low, but given enough time, it'll hit the condition.
Tip: If it takes too long on your system. Try only
a == 1 && a == 2
and changeMath.random()*3
toMath.random()*2
. Adding more and more to list drops the chance of hitting.By overriding
valueOf
in a class declaration, it can be done:What happens is that
valueOf
is called in each comparison operator. On the first one,a
will equal1
, on the second,a
will equal2
, and so on and so forth, because each timevalueOf
is called, the value ofa
is incremented.Therefore the console.log will fire and output (in my terminal anyways)
Thing: { value: 4}
, indicating the conditional was true.