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

Moderator's Note: Please resist the urge to change the code or delete this notification. The space pattern may be part of the question and therefore should not be falsified unnecessarily. If you are in the “spaces-insignificant” camp, you should be able to accept the code as is.

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

This is an interview question asked by a large technology company. This happened two weeks ago, but I'm still trying to find the answer. I know that we never write such code in our daily work, but I'm curious.

+2429
source share
30 answers

If you use how == works , you can simply create an object with a custom toString (or valueOf ) that changes what it returns each time it is used so 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!'); } 
Hide result

The reason this works is due to the use of the free equality operator. When using free equality, if one of the operands is different from the other, the engine will try to convert one to the other. In the case of the object on the left and the number on the right, it will try to convert the object to a number by first calling valueOf if it is callable, otherwise it will call toString . In this case, I used toString simply because it occurred to me, valueOf would make more sense. If I instead returned a string from toString , then the engine would try to convert the string to a number, giving us the same final result, albeit with a slightly longer path.

+3274
source

I could not resist - the other answers are undoubtedly correct, but you really cannot go past the following code:

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

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

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

Mark the validation check for the Mathias variable validator . If this strange interval were actually included in their question, I am sure that this is a hint of such an answer.

Do not do this. Really.

Edit: It occurred to me that (although it is not allowed to run a variable) Zero-width joiner and Zero-width character names are also allowed in variable names - see JavaScript obfuscation with zero-width characters - pros and cons? .

It will look like this:

 var a= 1; var a‍= 2; //one zero-width character var a‍‍= 3; //two zero-width characters (or you can use the other one) if(a==1&&a‍==2&&a‍‍==3) { console.log("Why hello there!") } 
Hide result
+2029
source

THIS IS POSSIBLE!

 var i = 0; with({ get a() { return ++i; } }) { if (a == 1 && a == 2 && a == 3) console.log("wohoo"); } 
Hide result

In this case, an absorber is used inside with expression to evaluate three different values. a

... this still does not mean that it should be used in real code ...

Even worse, this trick will also work using === .

  var i = 0; with({ get a() { return ++i; } }) { if (a !== a) console.log("yep, this is printed."); } 
Hide result
+607
source

Example without getters or value:

 a = [1,2,3]; a.join = a.shift; console.log(a == 1 && a == 2 && a == 3); 
Hide result

This works because == calls toString which calls .join for arrays.

Another solution using Symbol.toPrimitive which in ES6 is equivalent toString/valueOf :

 let i = 0; let a = { [Symbol.toPrimitive]: () => ++i }; console.log(a == 1 && a == 2 && a == 3); 
Hide result
+498
source

If asked if it is possible (NOT MUST), he may ask "a" to return a random number. It would be true if he sequentially generated 1, 2 and 3.

 with({ get a() { return Math.floor(Math.random()*4); } }){ for(var i=0;i<1000;i++){ if (a == 1 && a == 2 && a == 3){ console.log("after " + (i+1) + " trials, it becomes true finally!!!"); break; } } } 
Hide result
+264
source

If you cannot do anything without regular expressions:

 var a = { r: /\d/g, valueOf: function(){ return this.r.exec(123)[0] } } if (a == 1 && a == 2 && a == 3) { console.log("!") } 
Hide result

It works because of the custom method valueOf , which is called when the object is compared to a primitive (e.g. Number). The main trick is that a.valueOf returns a new value every time because it calls exec in the regular expression with the g flag, which causes the lastIndex this regular expression to be updated every time a match is found. So, for the first time this.r.lastIndex == 0 it matches 1 and updates lastIndex : this.r.lastIndex == 1 , so the next regular expression will match 2 , etc.

+208
source

This is possible if the variable a is accessed by, say, 2 web workers via SharedArrayBuffer, as well as some basic scripts. The possibility is low, but it is possible that when the code is compiled into machine code, the working networks update the variable a just in time, therefore the conditions a==1 , a==2 and a==3 are fulfilled.

This might be an example of race conditions in a multi-threaded environment provided by web workers and SharedArrayBuffer in JavaScript.

Here is the basic implementation above:

main.js

 // Main Thread const worker = new Worker('worker.js') const modifiers = [new Worker('modifier.js'), new Worker('modifier.js')] // Let 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, this happens after about 10 billion iterations on the first try:

enter image description here

Second attempt:

enter image description here

As I said, the chances will be low, but given enough time, he will fall into a state.

Tip. If your system has too much time. Try only a == 1 && a == 2 and change Math.random()*3 to Math.random()*2 . Adding more and more to the list reduces the chance of a hit.

+190
source

This can be done using the following in the global area. For nodejs use global instead of window in the code below.

 var val = 0; Object.defineProperty(window, 'a', { get: function() { return ++val; } }); if (a == 1 && a == 2 && a == 3) { console.log('yay'); } 
Hide result

This response abuses the implicit variables provided by the global scope in the execution context, defining the recipient to retrieve the variable.

+188
source

This is also possible with a series of self-configuring getters:

(This is similar to jontro's solution, but does not require a counter variable.)

 (() => { "use strict"; Object.defineProperty(this, "a", { "get": () => { Object.defineProperty(this, "a", { "get": () => { Object.defineProperty(this, "a", { "get": () => { return 3; } }); return 2; }, configurable: true }); return 1; }, configurable: true }); if (a == 1 && a == 2 && a == 3) { document.body.append("Yes, it's possible."); } })(); 
Hide result
+146
source

I don’t see that this answer has already been sent, so I will drop it in the mix too. This is similar to Jeff's answer with a half-width Hangul space.

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

You may notice a slight discrepancy with the second, but the first and third are identical with the naked eye. All 3 are different characters:

a - latin lowercase A
- The full width of the Latin lowercase A
- Cyrillic lowercase A

The general term for this is “homoglyphs”: different Unicode characters that look the same. It is usually difficult to get three that are completely indistinguishable, but in some cases you may be lucky. A, A, A, and Ꭺ will work better (Latin-A, Greek Alpha , Cyrillic-A, and Cherokee-A, respectively, unfortunately, the lowercase Greek letters and Cherokee are too different from Latin a : α , , and therefore not helps with the above snippet).

There is a whole class of Homoglyph Attacks, most often in fake domain names (for example, wikipedi.org (Cyrillic) vs wikipedia.org (Latin)), but it can also be displayed in code; commonly referred to as bribed (as mentioned in the commentary, the [underhanded] questions are no longer relevant to the PPCG topic, but usually it was the type of problem when such things appeared). I used this site to find the homoglyphs used for this answer.

+129
source

Alternatively, you can use a class and instance for verification for it.

 function A() { var value = 0; this.valueOf = function () { return ++value; }; } var a = new A; if (a == 1 && a == 2 && a == 3) { console.log('bingo!'); } 
Hide result

EDIT

Using ES6 classes, it will look like

 class A { constructor() { this.value = 0; this.valueOf(); } valueOf() { return this.value++; }; } let a = new A; if (a == 1 && a == 2 && a == 3) { console.log('bingo!'); } 
Hide result
+127
source

Yes it is possible! 😎

"JavaScript

 if‌=()=>!0; var a = 9; if‌(a==1 && a== 2 && a==3) { document.write("<h1>Yes, it is possible!😎</h1>") } 
Hide result

The above code is a short version (thanks to @Forivin for a note in the comments), and the following code is original:

 var a = 9; if‌(a==1 && a== 2 && a==3) { //console.log("Yes, it is possible!😎") document.write("<h1>Yes, it is possible!😎</h1>") } //-------------------------------------------- function if‌(){return true;} 
Hide result

If you just see the top of my code and run it, you say WOW, how?

Therefore, I think it’s enough to say “Yes”, maybe someone told you: “There is nothing impossible”

Trick: I used a hidden character after if how to make a function so that its name looks like if . In JavaScript, we cannot redefine keywords, so I have to use this method. This is fake, if , but it works for you in this case!


" C #

I also wrote a C # version (with an increase in the value of the property):

 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!😎"); } } 

Demo version

+102
source

Javascript

a == a +1

There are no integers in JavaScript , but only Number s, which are implemented as double-precision floating-point numbers.

This means that if the number a is large enough, it can be considered equal to three integer numbers:

 a = 100000000000000000 if (a == a+1 && a == a+2 && a == a+3){ console.log("Precision loss!"); } 
Hide result

True, this is not quite what the interviewer asked (he does not work with a=0 ), but this is not connected with a trick with hidden functions or operator overloading.

Other languages

For reference, in Ruby and Python there are a==1 && a==2 && a==3 solutions. With a little modification, this is also possible in Java.

Ruby

With 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 increase: a

 def a @a ||= 0 @a += 1 end if a == 1 && a == 2 && a == 3 puts "Don't do this!" end 

python

 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!") 

Java

Possible change to 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."); } } } 
+96
source

This is an inverted version of @Jeff 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; var1 = a; var2 = a; var3 = a; console.log( a ==ᅠ1 && a ==ᅠ2 && a ==ᅠ3 ); 
Hide result

* This answer can be simplified by using zero width (U + 200C) and zero width stoppers (U + 200D). Both of these characters are allowed inside identifiers, but not at the beginning:

 var a = 1; var a‌ = 2; var a‍ = 3; console.log(a == 1 && a‌ == 2 && a‍ == 3); /**** var a = 1; var a\u200c = 2; var a\u200d = 3; console.log(a == 1 && a\u200c == 2 && a\u200d == 3); ****/ 
Hide result

Other tricks are possible using the same idea, for example. Using Unicode variation selectors to create variables that look exactly the same ( a︀ = 1; a︁ = 2; a︀ == 1 && a︁ == 2; // true ).

+79
source

Rule number one of the interviews; never say impossible.

No need to hide character tricks.

 window.__defineGetter__( 'a', function(){ if( typeof i !== 'number' ){ // define i in the global namespace so that it not lost after this function runs i = 0; } return ++i; }); if( a == 1 && a == 2 && a == 3 ){ alert( 'Oh dear, what have we done?' ); } 
Hide result
+73
source

Honestly, is there a way to evaluate it as true or not (and, as others have shown, there are several ways), the answer I would look for, speaking as the person who conducted hundreds of interviews, would be something like:

"Well, maybe, under some strange conditions that are not immediately obvious to me ... but if I came across this in real code, I would use general debugging methods to find out how and why it does what it does I did, and then immediately refactored the code to avoid this situation ... but more importantly: I would NEVER write this code in the first place, because this is the very definition of the folded code, and I try to never write complex code. "

I think that some interviewers were offended by what was obviously caused by a very difficult question, but I am not against developers who have an opinion, especially when they can support this with considerations and can agree my question in a meaningful statement about themselves.

+68
source

If you ever ask such an interview question (or pay attention to some equally unexpected behavior in your code), think about what things can lead to behavior that seems impossible at first glance:

  1. Encoding : in this case, the variable you are looking at is not the one you consider. This can happen if you intentionally tinker with Unicode using homoglyphs or spaces to make the variable name look different, but encoding problems can also be entered accidentally, for example, when copying and pasting code from the Internet that contains unexpected Unicode code ( for example, because the content management system did some “automatic formatting,” such as replacing fl with Unicode “LATIN SMALL LIGATURE FL” (U + FB02)).

  2. Race conditions : a race condition may occur, that is, a situation where the code is not executed in the sequence expected by the developer. Race conditions are often in multi-threaded code, but multiple threads are not a prerequisite for race conditions. Asynchrony is sufficient (and do not be confused, asynchrony does not mean that several threads are used under the hood ).

    Please note that this is why JavaScript is also not free from race conditions just because it is single-threaded. See here a simple single-threaded but asynchronous example. In the context of one statement, a race condition, however, would be rather difficult to get into JavaScript.

    JavaScript with web workers is a bit different since you can have multiple threads. @mehulmpt showed us great proof of concept using web workers .

  3. Side effects : a side effect of the equality comparison operation (which should not be as obvious as in the examples here, often the side effects are very subtle).

This kind of questions can appear in many programming languages, not just JavaScript, so we don’t see one of the classic JavaScript WTFs here 1.

Of course, the interview question and the samples here all look very far-fetched. But they are a good reminder that:

  • Side effects can become really unpleasant and that a well-designed program should be free of unwanted side effects.
  • Multithreaded and mutable state can be problematic.
  • Incorrect character encoding and proper string handling can lead to unpleasant errors.

1 For example, you can find an example in a completely different programming language (C #) exposing a side effect (obvious) here .

+42
source

Here is another option, using an array to drop out any values ​​you want.

 const a = { n: [3,2,1], toString: function () { return anpop(); } } if(a == 1 && a == 2 && a == 3) { console.log('Yes'); } 
Hide result
+41
source

Ok, another hack with generators:

 const value = function* () { let i = 0; while(true) yield ++i; }(); Object.defineProperty(this, 'a', { get() { return value.next().value; } }); if (a === 1 && a === 2 && a === 3) { console.log('yo!'); } 
Hide result
+31
source

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 the target (the first parameter), but intercept operations on the target (in this case, the “get property” operation), so it is possible to do something different from the default behavior of the object. In this case, the “get property” action is invoked when a == forces its type to compare it with each number. It happens:

  1. We create the target { i: 0 } where property i is our counter
  2. We create a proxy for the target and assign it a
  3. For each a == comparison, the type is cast to a primitive value of a
  4. a[Symbol.toPrimitive]() this type results in an internal call a[Symbol.toPrimitive]()
  5. The proxy intercepts the receipt of the function a[Symbol.toPrimitive] using the "receive handler"
  6. The "get" proxy handler checks that the received property has the form Symbol.toPrimitive , in which case it increases the value, and then returns the counter from the target object: ++target.i . If another property is retrieved, we simply return 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 other answers, this only works with arbitrary equality checking ( == ), because strict equality checks ( === ) do not lead to type coercion, which can be intercepted by Proxies.

+28
source

In fact, the answer to the first part of the question is "Yes" in each programming language. For example, this applies to C / C ++:

 #define a (b++) int b = 1; if (a ==1 && a== 2 && a==3) { std::cout << "Yes, it possible!" << std::endl; } else { std::cout << "it impossible!" << std::endl; } 
+27
source

The same, but different, but still one (it can be "checked" several times):

 const a = { valueOf: () => this.n = (this.n || 0) % 3 + 1} if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); } if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); } 
Hide result

My idea began with how the type equation of an object of a type works.

+26
source

ECMAScript 6 answer that uses characters:

 const a = {value: 1}; a[Symbol.toPrimitive] = function() { return this.value++ }; console.log((a == 1 && a == 2 && a == 3)); 

Thanks to == use, JavaScript should force something close to the second operand ( a 1 , 2 , 3 in this case). But before JavaScript tries Symbol.toPrimitive enforce itself, it tries to call Symbol.toPrimitive . If you provide Symbol.toPrimitive JavaScript, use the value returned by your function. If not, JavaScript will call valueOf .

+23
source

I think this is the minimum code to implement it:

 i=0,a={valueOf:()=>++i} if (a == 1 && a == 2 && a == 3) { console.log('Mind === Blown'); } 
Hide result

Create a dummy object with a custom valueOf that increments the global variable i for each call. 23 characters!

+23
source

defineProperty , !

 var _a = 1 Object.defineProperty(this, "a", { "get": () => { return _a++; }, configurable: true }); console.log(a) console.log(a) console.log(a) 
Hide result
+12
source

, , == . === .

 const a = { i: 0; valueOf: function() { return this.i++; } } if(a == 1 && a == 2 && a == 3) // true 

valueOf toString , == .

 if(a === 1 && a === 2 && a === 3) // false 

valueOf toString .

+2
source

valueOf , :

 class Thing { constructor() { this.value = 1; } valueOf() { return this.value++; } } const a = new Thing(); if(a == 1 && a == 2 && a == 3) { console.log(a); } 

, , valueOf . a 1 , a 2 , , .., , valueOf , a .

Therefore, console.log will run and output (anyway in my terminal) Thing: { value: 4}, indicating that the condition was true.

0
source

That's a good question.I also wanted to add a Java implementation because the update valueOf()basically overrides the base class function. It took me a few minutes to figure out how this works in JS, so I matched it with Java for understanding.

 public class TestClass { int value; TestClass() { this.value = 0; } @Override public String toString() { System.out.println("current " + this.value); this.value++; return String.valueOf(this.value); } } class CallingClass { public static void main(String[] args) { TestClass object = new TestClass(); if (object.toString().equals("1") && object.toString().equals("2") && object.toString().equals("3")) { System.out.print("it here"); } } } 
0
source

try this:
The same, but different, but still (you can "check" several times):

 const a = { valueOf: () => this.n = (this.n || 0) % 3 + 1} if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); } if(a == 1 && a == 2 && a == 3) { console.log('Hello World!'); } 
0
source

Even without naming confusion, overloading, or random variables, it a == 1 && a == 2 && a == 3can return truein multi-threaded environments, as the value acan change between each comparison if it is not thread safe.

-3
source

Source: https://habr.com/ru/post/1274935/


All Articles