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 related to
javascript
ecmascript-6
This is also possible using a series of self-overwriting getters:
(This is similar to jontro's solution, but doesn't require a counter variable.)
(() => {_x000D_
"use strict";_x000D_
Object.defineProperty(this, "a", {_x000D_
"get": () => {_x000D_
Object.defineProperty(this, "a", {_x000D_
"get": () => {_x000D_
Object.defineProperty(this, "a", {_x000D_
"get": () => {_x000D_
return 3;_x000D_
}_x000D_
});_x000D_
return 2;_x000D_
},_x000D_
configurable: true_x000D_
});_x000D_
return 1;_x000D_
},_x000D_
configurable: true_x000D_
});_x000D_
if (a == 1 && a == 2 && a == 3) {_x000D_
document.body.append("Yes, it’s possible.");_x000D_
}_x000D_
})();
_x000D_
When you can't do anything without regular expressions:
var a = {_x000D_
r: /\d/g, _x000D_
valueOf: function(){_x000D_
return this.r.exec(123)[0]_x000D_
}_x000D_
}_x000D_
_x000D_
if (a == 1 && a == 2 && a == 3) {_x000D_
console.log("!")_x000D_
}
_x000D_
It works because of custom valueOf
method that is called when Object compared with primitive (such as Number). Main trick is that a.valueOf
returns new value every time because it's calling exec
on regular expression with g
flag, which causing updating lastIndex
of that regular expression every time match is found. So first time this.r.lastIndex == 0
, it matches 1
and updates lastIndex
: this.r.lastIndex == 1
, so next time regex will match 2
and so on.
Using Proxies:
var a = new Proxy({ i: 0 }, {
get: (target, name) => name === Symbol.toPrimitive ? () => ++target.i : target[name],
});
console.log(a == 1 && a == 2 && a == 3);
Proxies basically pretend to be a target object (the first parameter), but intercept operations on the target object (in this case the "get property" operation) so that there is an opportunity to do something other than the default object behavior. In this case the "get property" action is called on a
when ==
coerces its type in order to compare it to each number. This happens:
{ i: 0 }
, where the i
property is our countera
a ==
comparison, a
's type is coerced to a primitive valuea[Symbol.toPrimitive]()
internallya[Symbol.toPrimitive]
function using the "get handler"Symbol.toPrimitive
, in which case it increments and then returns the counter from the target object: ++target.i
. If a different property is being retrieved, we just fall back to returning the default property value, target[name]
So:
var a = ...; // a.valueOf == target.i == 0
a == 1 && // a == ++target.i == 1
a == 2 && // a == ++target.i == 2
a == 3 // a == ++target.i == 3
As with most of the other answers, this only works with a loose equality check (==
), because strict equality checks (===
) do not do type coercion that the Proxy can intercept.
This is an inverted version of @Jeff's answer* where a hidden character (U+115F, U+1160 or U+3164) is used to create variables that look like 1
, 2
and 3
.
var a = 1;_x000D_
var ?1 = a;_x000D_
var ?2 = a;_x000D_
var ?3 = a;_x000D_
console.log( a ==?1 && a ==?2 && a ==?3 );
_x000D_
* That answer can be simplified by using zero width non-joiner (U+200C) and zero width joiner (U+200D). Both of these characters are allowed inside identifiers but not at the beginning:
var a = 1;_x000D_
var a? = 2;_x000D_
var a? = 3;_x000D_
console.log(a == 1 && a? == 2 && a? == 3);_x000D_
_x000D_
/****_x000D_
var a = 1;_x000D_
var a\u200c = 2;_x000D_
var a\u200d = 3;_x000D_
console.log(a == 1 && a\u200c == 2 && a\u200d == 3);_x000D_
****/
_x000D_
Other tricks are possible using the same idea e.g. by using Unicode variation selectors to create variables that look exactly alike (a? = 1; a? = 2; a? == 1 && a? == 2; // true
).
Alternatively, you could use a class for it and an instance for the check.
function A() {_x000D_
var value = 0;_x000D_
this.valueOf = function () { return ++value; };_x000D_
}_x000D_
_x000D_
var a = new A;_x000D_
_x000D_
if (a == 1 && a == 2 && a == 3) {_x000D_
console.log('bingo!');_x000D_
}
_x000D_
EDIT
Using ES6 classes it would look like this
class A {_x000D_
constructor() {_x000D_
this.value = 0;_x000D_
this.valueOf();_x000D_
}_x000D_
valueOf() {_x000D_
return this.value++;_x000D_
};_x000D_
}_x000D_
_x000D_
let a = new A;_x000D_
_x000D_
if (a == 1 && a == 2 && a == 3) {_x000D_
console.log('bingo!');_x000D_
}
_x000D_
if?=()=>!0;_x000D_
var a = 9;_x000D_
_x000D_
if?(a==1 && a== 2 && a==3)_x000D_
{_x000D_
document.write("<h1>Yes, it is possible!</h1>")_x000D_
}
_x000D_
The above code is a short version (thanks to @Forivin for its note in comments) and the following code is original:
var a = 9;_x000D_
_x000D_
if?(a==1 && a== 2 && a==3)_x000D_
{_x000D_
//console.log("Yes, it is possible!")_x000D_
document.write("<h1>Yes, it is possible!</h1>")_x000D_
}_x000D_
_x000D_
//--------------------------------------------_x000D_
_x000D_
function if?(){return true;}
_x000D_
If you just see top side of my code and run it you say WOW, how?
So I think it is enough to say Yes, it is possible to someone that said to you: Nothing is impossible
Trick: I used a hidden character after
if
to make a function that its name is similar toif
. In JavaScript we can not override keywords so I forced to use this way. It is a fakeif
, but it works for you in this case!
Also I wrote a C# version (with increase property value technic):
static int _a;
public static int a => ++_a;
public static void Main()
{
if(a==1 && a==2 && a==3)
{
Console.WriteLine("Yes, it is possible!");
}
}
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.
It can be accomplished using the following in the global scope. For nodejs
use global
instead of window
in the code below.
var val = 0;_x000D_
Object.defineProperty(window, 'a', {_x000D_
get: function() {_x000D_
return ++val;_x000D_
}_x000D_
});_x000D_
if (a == 1 && a == 2 && a == 3) {_x000D_
console.log('yay');_x000D_
}
_x000D_
This answer abuses the implicit variables provided by the global scope in the execution context by defining a getter to retrieve the variable.
Same, but different, but still same (can be "tested" multiple times):
const a = { valueOf: () => this.n = (this.n || 0) % 3 + 1}_x000D_
_x000D_
if(a == 1 && a == 2 && a == 3) {_x000D_
console.log('Hello World!');_x000D_
}_x000D_
_x000D_
if(a == 1 && a == 2 && a == 3) {_x000D_
console.log('Hello World!');_x000D_
}
_x000D_
My idea started from how Number object type equation works.
Here's another variation, using an array to pop off whatever values you want.
const a = {_x000D_
n: [3,2,1],_x000D_
toString: function () {_x000D_
return a.n.pop();_x000D_
}_x000D_
}_x000D_
_x000D_
if(a == 1 && a == 2 && a == 3) {_x000D_
console.log('Yes');_x000D_
}
_x000D_
Rule number one of interviews; never say impossible.
No need for hidden character trickery.
window.__defineGetter__( 'a', function(){_x000D_
if( typeof i !== 'number' ){_x000D_
// define i in the global namespace so that it's not lost after this function runs_x000D_
i = 0;_x000D_
}_x000D_
return ++i;_x000D_
});_x000D_
_x000D_
if( a == 1 && a == 2 && a == 3 ){_x000D_
alert( 'Oh dear, what have we done?' );_x000D_
}
_x000D_
An ECMAScript 6 answer that makes use of Symbols:
const a = {value: 1};
a[Symbol.toPrimitive] = function() { return this.value++ };
console.log((a == 1 && a == 2 && a == 3));
Due to ==
usage, JavaScript is supposed to coerce a
into something close to the second operand (1
, 2
, 3
in this case). But before JavaScript tries to figure coercing on its own, it tries to call Symbol.toPrimitive
. If you provide Symbol.toPrimitive
JavaScript would use the value your function returns. If not, JavaScript would call valueOf
.
I couldn't resist - the other answers are undoubtedly true, but you really can't walk past the following code:
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_
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:
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_
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:
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_
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 variable a
just in time so the conditions a==1
, a==2
and a==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
// Main Thread
const worker = new Worker('worker.js')
const modifiers = [new Worker('modifier.js'), new Worker('modifier.js')] // Let's use 2 workers
const sab = new SharedArrayBuffer(1)
modifiers.forEach(m => m.postMessage(sab))
worker.postMessage(sab)
worker.js
let array
Object.defineProperty(self, 'a', {
get() {
return array[0]
}
});
addEventListener('message', ({data}) => {
array = new Uint8Array(data)
let count = 0
do {
var res = a == 1 && a == 2 && a == 3
++count
} while(res == false) // just for clarity. !res is fine
console.log(`It happened after ${count} iterations`)
console.log('You should\'ve never seen this')
})
modifier.js
addEventListener('message' , ({data}) => {
setInterval( () => {
new Uint8Array(data)[0] = Math.floor(Math.random()*3) + 1
})
})
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 change Math.random()*3
to Math.random()*2
. Adding more and more to list drops the chance of hitting.
If it is asked if it is possible (not MUST), it can ask "a" to return a random number. It would be true if it generates 1, 2, and 3 sequentially.
with({_x000D_
get a() {_x000D_
return Math.floor(Math.random()*4);_x000D_
}_x000D_
}){_x000D_
for(var i=0;i<1000;i++){_x000D_
if (a == 1 && a == 2 && a == 3){_x000D_
console.log("after " + (i+1) + " trials, it becomes true finally!!!");_x000D_
break;_x000D_
}_x000D_
}_x000D_
}
_x000D_
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:
a = 100000000000000000_x000D_
if (a == a+1 && a == a+2 && a == a+3){_x000D_
console.log("Precision loss!");_x000D_
}
_x000D_
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.
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.
With a custom ==
:
class A
def ==(o)
true
end
end
a = A.new
if a == 1 && a == 2 && a == 3
puts "Don't do this!"
end
Or an increasing a
:
def a
@a ||= 0
@a += 1
end
if a == 1 && a == 2 && a == 3
puts "Don't do this!"
end
class A:
def __eq__(self, who_cares):
return True
a = A()
if a == 1 and a == 2 and a == 3:
print("Don't do that!")
It's possible to modify Java Integer
cache:
package stackoverflow;
import java.lang.reflect.Field;
public class IntegerMess
{
public static void main(String[] args) throws Exception {
Field valueField = Integer.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.setInt(1, valueField.getInt(42));
valueField.setInt(2, valueField.getInt(42));
valueField.setInt(3, valueField.getInt(42));
valueField.setAccessible(false);
Integer a = 42;
if (a.equals(1) && a.equals(2) && a.equals(3)) {
System.out.println("Bad idea.");
}
}
}
By overriding valueOf
in a class declaration, it can be done:
class Thing {
constructor() {
this.value = 1;
}
valueOf() {
return this.value++;
}
}
const a = new Thing();
if(a == 1 && a == 2 && a == 3) {
console.log(a);
}
What happens is that valueOf
is called in each comparison operator. On the first one, a
will equal 1
, on the second, a
will equal 2
, and so on and so forth, because each time valueOf
is called, the value of a
is incremented.
Therefore the console.log will fire and output (in my terminal anyways) Thing: { value: 4}
, indicating the conditional was true.
I think this is the minimal code to implement it:
i=0,a={valueOf:()=>++i}_x000D_
_x000D_
if (a == 1 && a == 2 && a == 3) {_x000D_
console.log('Mind === Blown');_x000D_
}
_x000D_
Creating a dummy object with a custom valueOf
that increments a global variable i
on each call. 23 characters!
Example without getters or valueOf:
a = [1,2,3];_x000D_
a.join = a.shift;_x000D_
console.log(a == 1 && a == 2 && a == 3);
_x000D_
This works because ==
invokes toString
which calls .join
for Arrays.
Another solution, using Symbol.toPrimitive
which is an ES6 equivalent of toString/valueOf
:
let i = 0;_x000D_
let a = { [Symbol.toPrimitive]: () => ++i };_x000D_
_x000D_
console.log(a == 1 && a == 2 && a == 3);
_x000D_
I don't see this answer already posted, so I'll throw this one into the mix too. This is similar to Jeff's answer with the half-width Hangul space.
var a = 1;_x000D_
var a = 2;_x000D_
var ? = 3;_x000D_
if(a == 1 && a == 2 && ? == 3) {_x000D_
console.log("Why hello there!")_x000D_
}
_x000D_
You might notice a slight discrepancy with the second one, but the first and third are identical to the naked eye. All 3 are distinct characters:
a
- Latin lower case A
a
- Full Width Latin lower case A
?
- Cyrillic lower case A
The generic term for this is "homoglyphs": different unicode characters that look the same. Typically hard to get three that are utterly indistinguishable, but in some cases you can get lucky. A, ?, ?, and ? would work better (Latin-A, Greek Alpha, Cyrillic-A, and Cherokee-A respectively; unfortunately the Greek and Cherokee lower-case letters are too different from the Latin a
: a
,?
, and so doesn't help with the above snippet).
There's an entire class of Homoglyph Attacks out there, most commonly in fake domain names (eg. wikipedi?.org
(Cyrillic) vs wikipedia.org
(Latin)), but it can show up in code as well; typically referred to as being underhanded (as mentioned in a comment, [underhanded] questions are now off-topic on PPCG, but used to be a type of challenge where these sorts of things would show up). I used this website to find the homoglyphs used for this answer.
Honestly though, whether there is a way for it to evaluate to true or not (and as others have shown, there are multiple ways), the answer I'd be looking for, speaking as someone who has conducted hundreds of interviews, would be something along the lines of:
"Well, maybe yes under some weird set of circumstances that aren't immediately obvious to me... but if I encountered this in real code then I would use common debugging techniques to figure out how and why it was doing what it was doing and then immediately refactor the code to avoid that situation... but more importantly: I would absolutely NEVER write that code in the first place because that is the very definition of convoluted code, and I strive to never write convoluted code".
I guess some interviewers would take offense to having what is obviously meant to be a very tricky question called out, but I don't mind developers who have an opinion, especially when they can back it up with reasoned thought and can dovetail my question into a meaningful statement about themselves.
This one uses the defineProperty with a nice side-effect causing global variable!
var _a = 1_x000D_
_x000D_
Object.defineProperty(this, "a", {_x000D_
"get": () => {_x000D_
return _a++;_x000D_
},_x000D_
configurable: true_x000D_
});_x000D_
_x000D_
console.log(a)_x000D_
console.log(a)_x000D_
console.log(a)
_x000D_
Actually the answer to the first part of the question is "Yes" in every programming language. For example, this is in the case of C/C++:
#define a (b++)
int b = 1;
if (a ==1 && a== 2 && a==3) {
std::cout << "Yes, it's possible!" << std::endl;
} else {
std::cout << "it's impossible!" << std::endl;
}
Okay, another hack with generators:
const value = function* () {_x000D_
let i = 0;_x000D_
while(true) yield ++i;_x000D_
}();_x000D_
_x000D_
Object.defineProperty(this, 'a', {_x000D_
get() {_x000D_
return value.next().value;_x000D_
}_x000D_
});_x000D_
_x000D_
if (a === 1 && a === 2 && a === 3) {_x000D_
console.log('yo!');_x000D_
}
_x000D_
IT IS POSSIBLE!
var i = 0;_x000D_
_x000D_
with({_x000D_
get a() {_x000D_
return ++i;_x000D_
}_x000D_
}) {_x000D_
if (a == 1 && a == 2 && a == 3)_x000D_
console.log("wohoo");_x000D_
}
_x000D_
This uses a getter inside of a with
statement to let a
evaluate to three different values.
... this still does not mean this should be used in real code...
Even worse, this trick will also work with the use of ===
.
var i = 0;_x000D_
_x000D_
with({_x000D_
get a() {_x000D_
return ++i;_x000D_
}_x000D_
}) {_x000D_
if (a !== a)_x000D_
console.log("yep, this is printed.");_x000D_
}
_x000D_
Source: Stackoverflow.com