2669

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.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Dimpu Aravind Buddha
  • 9,505
  • 4
  • 17
  • 23
  • 12
    Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/163228/discussion-on-question-by-dimpu-aravind-buddha-in-javascript-how-can-you-have-th). – deceze Jan 16 '18 at 08:20
  • 2
    note that even if the spaces are corrected, it's still possible for the original to have been using the invisible characters and appear to have correct spacing. `(aᅠ== 1 && a == 2 &&ᅠa == 3)` (you simply alternate where the real spaces are) – Kevin B Jan 16 '18 at 21:07
  • 123
    To the people that apparently voted to cloae this as _too broad_: is that a dig at Javascript, saying that there are too many valid answers? – tomsmeding Jan 16 '18 at 23:15
  • 3
    @TrevorBoydSmith: This would work in many languages besides JavaScript, e.g. using operator overloading with side-effects in C# or Java. – Dirk Vollmar Jan 17 '18 at 08:58
  • 3
    if security is an issue in one's code - and it should be - asking about nuances and curios (even if they're obscure) isn't necessarily a bad thing. If the question is more than intellectual onanism on the part of the interviewer, it stands to be a way of opening up discussion with the candidate... so @ghord, I wouldn't throw the baby out with the bathwater, this is a perfectly acceptable tool; it's what you do with it at interview that makes it worthwhile – Jay Edwards Jan 17 '18 at 11:52
  • 2
    @ghord kinda reasonable if the interviewer expects that the interviewee has some insight of the ECMAscript. If you know the difference between `==` and `===` then you can answer this question easily. Although the korean character trick is a nifty one. – KarelG Jan 17 '18 at 12:49
  • 32
    Some people sit around philosophizing about what's possible. Others focus their efforts on whether or not they are building viable, business correct products for their clients. IMO, this question has no practical utility beyond the fact that you should never ask these kinds of questions in an interview or write this kind of code. That's why it should be closed. I mean really, does the business realize they paid somebody real money to sit around and talk about this stuff? – P.Brian.Mackey Jan 17 '18 at 16:10
  • 1
    What's the threading model of JavaScript? In many languages (and depending on the definition of `a` - e.g. with `volatile` in C), reading a simple variable may return different results at different times if it's modified by something external. – Toby Speight Jan 17 '18 at 16:21
  • 6
    @TobySpeight javascript executes in a single threaded context. Certain actions do run on a separate thread, but code runs synchronously and therefore that couldn't happen in javascript, at least not with an expression like in this question. – Kevin B Jan 17 '18 at 16:24
  • 9
    This question does have some merit in that it calls for an understanding of the awfulness and danger of the language you'll be working with. – R.. GitHub STOP HELPING ICE Jan 17 '18 at 16:43
  • 3
    @R..Just because a developer is allowed to do stupid things doesn't mean the language is bad. Read JavaScript the good parts. That's kind-a the point of the book. – P.Brian.Mackey Jan 17 '18 at 17:56
  • 20
    After reading the answers, the morals of the story are: don't use `==` when you mean `===`, have a coding standard that bans non-ASCII variable names, and have a linting process which enforces the previous two morals. – Jesse C. Slicer Jan 17 '18 at 18:00
  • 5
    @JesseC.Slicer Makes me wonder if the interviewer would have accepted “I wouldn’t know, I only ever use `===` like a good Javascript developer,” as an answer. (Though personally I do have some quibbles with that absolutism, at least on small projects.) – KRyan Jan 17 '18 at 19:13
  • 1
    @KRyan certainly there are perfectly cromulent reasons why `==` and `!=` exist -- it's just a matter of the developer putting the appropriate lint ignore on those (hopefully few) usages. – Jesse C. Slicer Jan 17 '18 at 19:36
  • 92
    **Moderator note:** Stack Overflow has had a history of people chiming in with answers in different languages to the one in question. These *are* attempts to answer the question because they are solutions to the general problem, albeit in a different language. Please refrain from flagging them as "not an answer". Having said that, please also refrain from posting more answers in different languages - there is a reason this question is specific to JavaScript, as pointed out by comments under some of these other answers, and there is a reason we like our language-specific questions to remain so. – BoltClock Jan 18 '18 at 05:31
  • 6
    worth a view: [Invoking a function without parentheses](https://stackoverflow.com/questions/35949554/invoking-a-function-without-parentheses) – Nina Scholz Jan 18 '18 at 17:53
  • @DirkVollmar Operator overloading in Java? – Solomon Ucko Jan 19 '19 at 14:41

29 Answers29

3482

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.

user4020527
  • 1
  • 8
  • 20
Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • 77
    Could you achieve this by altering the implied `valueOf()` operation? – Sterling Archer Jan 15 '18 at 20:37
  • 49
    Yes, valueOf works in place of toString for the same reason – Kevin B Jan 15 '18 at 20:38
  • 4
    Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/163229/discussion-on-answer-by-kevin-b-in-javascript-how-can-you-have-the-statement-if). – deceze Jan 16 '18 at 08:24
  • 1
    This is definitely one of my most favorite answers. Loved the trick and I learned a lot from it. hmmm, I was thinking about is there any way to access the right side operator there? Then it could be always true by any given value – Mohammad Kermani Jan 16 '18 at 11:14
  • 2
    fortunately, no. – Kevin B Jan 16 '18 at 11:17
  • 1
    If `i` and `1`, `2`, and `3` are numbers, why is it calling `toString`? – AncientSwordRage Jan 16 '18 at 11:29
  • 16
    According to [this](http://www.ecma-international.org/ecma-262/5.1/#sec-8.12.8) a number conversion will be tried first so `valueOf` is slightly better. – Salman A Jan 16 '18 at 12:31
  • 7
    @Pureferret the left-hand side of the equality comparison is an object, not a number. That that object has a number property on `i` doesn't bother the engine. ;) – tomsmeding Jan 16 '18 at 13:07
  • Just curious, isn't such expression `a == 1 && a == 2 && a == 3` subject to JIT optimization? – rkosegi Jan 16 '18 at 20:03
  • @rkosegi well doesn't seem to be optimized in this scenario. If it was compiled it would likely optimize the expression to false – Cruncher Jan 17 '18 at 01:00
  • 2
    why not using **`this`**? i.e.,: `toString: function() { return this.i++; }` – ryenus Jan 17 '18 at 01:19
  • 2
    @rkosegi no, its not possible in js. Code behaves as defined in the specs, even if optimized – Jonas Wilms Jan 17 '18 at 06:21
  • 1
    Just curious, can we support a === 1 && a === 2 && a === 3? for example trying to override Number.constructor and using boxing/unboxing? – Anatoli Klamer Jan 17 '18 at 10:28
  • 2
    @zxxc No, numbers and `Number`s are different (one is a primitive and one is an object, so they will immediately fail strict `===` comparison). Number primitives have no constructor (nor does any primitive). – apsillers Jan 17 '18 at 13:45
  • @zxxc that wont work with this answer, but with the three following – Jonas Wilms Jan 17 '18 at 15:59
  • 2
    Just an addition to always hold the condition: `const a = { i: 0, toString: function () { var returned = (++a.i); if(a.i >= 3) { a.i = 0; } return returned; } }` – me_digvijay Jan 18 '18 at 12:15
  • Does order of evaluation always from left to right? Asking because depending on the js engine, should we write the i++ statement as i--? – Onur Jan 21 '18 at 10:24
  • What is the value of `a` when it's being compared to the numbers? – hungrykoala Jan 24 '18 at 07:38
  • when it is finally compared to the number, it is the number it is comparing to. but, a contains an object. – Kevin B Jan 24 '18 at 07:57
2149

I couldn't resist - the other answers are undoubtedly true, but you really can't walk 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!")
}

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;
var a = 2;
var _a = 3;
if(a_==1 && a== 2 &&_a==3) {
    console.log("Why hello there!")
}

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;
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!")
}
Jeff
  • 12,555
  • 5
  • 33
  • 60
  • 389
    Judging by the odd spacing in the original question, I think this is EXACTLY the answer the interview question was looking for - exploiting non-space characters that look like spaces. Good spot! – Baracus Jan 16 '18 at 07:09
  • 22
    @Baracus It was RonJohn who noticed the weird spacing in his comment on Kevin's answer which reminded me of this (awful) technique, so I can't take credit for spotting it. I was kinda surprised noone had already answered with this though, as it went around my work a few years ago because of a blog post somewhere - I kinda assumed it was pretty common knowledge by now. – Jeff Jan 16 '18 at 07:12
  • Could you use U+2060 or similar instead? – Taemyr Jan 16 '18 at 11:24
  • 109
    Of course, this is banned as a [standard loophole](https://codegolf.meta.stackexchange.com/a/1657/32352), which also applies to interviews. [citation needed] – Sanchises Jan 16 '18 at 12:23
  • heh, i could imagine this being more of a mindbender if strict equal were used, however, that would have probably made the answer more obvious if this was what the interviewer intended to be the result. – Kevin B Jan 16 '18 at 13:00
  • 15
    Considering the original spacing, it might be even worse, i.e. a variable `var ᅠ2 = 3` has been used; so there are the three variables `aᅠᅠ= 1, ᅠ2 = 3, a = 3` (`a␣ = 1, ␣2 = 3, a = 3`, so that `(a␣==1 && a==␣2 && a==3)`)… – Holger Jan 17 '18 at 07:15
  • 1
    can any one point out the difference among these three variables ?I am having a hard time understanding the answer even after reading the explanation.My initial thought is All three variables looks same to me and i think they will overwrite each other and only the last one will prevail.Then how come they behave differently? – AL-zami Jan 17 '18 at 16:11
  • 1
    A properly configured static code analysis tool should catch bad code like this and report this at build time. No way such code should be allowed in one's repository. – jkwuc89 Jan 17 '18 at 16:29
  • 3
    @AL-zami there is an extra character in two of the variables, which shows on your screen as a space, but is interpreted as part of the identifier, meaning there are three separate variables - _a, a and a_ - the extra character is the Hangul half-width space. – Jeff Jan 17 '18 at 18:27
  • 1
    @holger ha! There might be only one variable “a”, and 1, 2 and 3 could all be defined as variables with the same value as a. Good times... – Jeff Jan 17 '18 at 18:28
  • Well, there is no visible space before the `1` or `3`, but I’m not precluding that there is a zero-width character that is a valid identifier start… I don’t know, how JavaScript handles this, but Java allows some fun using the LTR/RTL control characters… – Holger Jan 17 '18 at 18:32
  • @Holger just did some experimenting - it appears that the ltr character at least doesn't work, either at the start or at the end of an identifier. For reference, here it is: "‎" – Jeff Jan 17 '18 at 20:34
  • @Holger I just found out that the Zero-width joiner and non-joiner characters do work in variable names (albeit not as a starting character) - see edit. Good times... – Jeff Jan 25 '18 at 19:49
649

IT IS POSSIBLE!

var i = 0;

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

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;

  with({
    get a() {
      return ++i;
    }
  }) {
    if (a !== a)
      console.log("yep, this is printed.");
  }
Pac0
  • 21,465
  • 8
  • 65
  • 74
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • 68
    Yes I was trying the same thing :) So the correct answer in the interview would be, "It cannot happen in **my** code because I never use `with`." – Pointy Jan 15 '18 at 20:42
  • 8
    @Pointy - And, I program in strict mode where `with` is not allowed. – jfriend00 Jan 15 '18 at 20:44
  • 7
    @Pointy in the accepted answer they do something similar without the `with` so it can happen – J_rite Jan 16 '18 at 11:17
  • 2
    @jorrit no one would use `==`. And `===` prevents the accepted answer – Jonas Wilms Jan 16 '18 at 12:48
  • 4
    @JonasW. A lot of people still use `==` but I haven't seen `with` since ... well actually never outside of JS documentation where it says "please don't use that". Anyway, a nice solution. – wortwart Jan 16 '18 at 19:31
  • @Pointy If only the part that is shown exists then a is not defined and question does not have any sense. But for any normal person this question makes sense so every normal person assumes that there is some additional code around that was simply not presented. – AmokHuginnsson Jan 16 '18 at 20:43
  • 1
    Notice, with this solution the condition will evaluate to true even if you will use `===`! – Ori Shalom Jan 24 '18 at 11:39
  • 2
    I definitely find this the most unique, creative and non-sneaky way (weird spacing) of solving this! – Isaac Abramowitz Jul 25 '18 at 19:39
  • 1
    I added example with triple equals in the answer. (And yes, you can do it without `with` to lure the `==` checks) – Pac0 Oct 05 '18 at 10:10
  • mdn prohibits usage of with from ES5 in strict mode. And I do agree with their reasons. check here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with – Leela Venkatesh K Feb 13 '19 at 04:45
  • @Pointy It's possible without `with` (even with strict equality). Here's one such way it could happen: https://stackoverflow.com/a/48270332/1945651 – JLRishe Oct 25 '20 at 13:33
565

Example without getters or valueOf:

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

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;
let a = { [Symbol.toPrimitive]: () => ++i };

console.log(a == 1 && a == 2 && a == 3);
georg
  • 211,518
  • 52
  • 313
  • 390
  • 11
    `without valueOf`, well... its more indirect but basically the same thing. – Jonas Wilms Jan 17 '18 at 15:39
  • 12
    I really like this solution because you don't override anything but the objects own join function, and it's just a very clean and easy to read hack that makes the logic evaluate to true. – Alex Pedersen Jan 17 '18 at 15:47
  • 29
    Honestly I think this is the best answer. It involves nothing out of the ordinary, just setting a few values. Very easy to understand even with basic JS knowledge. Well done. – Zac Delventhal Jan 17 '18 at 17:05
  • 17
    This makes so much sense it almost feels useful. – Andrew Jan 17 '18 at 20:47
  • 8
    I knew most answers would be about abusing `toString` or `valueOf` but this one caught me completely out of guard. Very clever and I didn't know it did call `.join`internally, but it makes total sense. – GBarroso Jan 18 '18 at 03:02
  • 2
    `a.join = a.shift` is genius. Evil genius, but genius nonetheless. – Justin Morgan - On strike Dec 14 '18 at 20:28
274

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({
  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;
    }
  }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ocomfd
  • 4,010
  • 2
  • 10
  • 19
  • 112
    I would deliberately give this answer even if I knew the other solutions, because it answers the question but is obviously not what they were after. Play stupid games, win stupid prizes. – ESR Jan 17 '18 at 03:41
  • 3
    But what if it takes more than 1000 trials? – Piyin Jan 22 '18 at 14:33
  • 13
    @Piyin If it takes more than 1000 trials you win a prize! – Skeets Jan 22 '18 at 17:19
  • 6
    I like this answer because taking it to the extreme suggests that this is possible in _any_ language if the cpu's registers/cache get hit with enough cosmic rays while the program is running, or if one deliberately performs a power glitch such that the failure branch of the if conditional doesn't actually jump. – Ponkadoodle Jan 23 '18 at 00:54
  • 1
    Lowest: 1, Highest: 412. – KyleFairns Jan 30 '18 at 10:09
  • Lowest: 1, Highest: _______. I'd like my prize now, please – Samathingamajig Aug 14 '22 at 00:31
  • 1
    @Piyin Probability of that is 1.44735635e-7 – AspectOfTheNoob Jan 09 '23 at 02:17
216

When you can't 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("!")
}

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.

Kos
  • 4,890
  • 9
  • 38
  • 42
  • 22
    @Abdillah a regex object will remember the last index it matches, call `exec` again will begin searching from that index. [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec#Description) is not very clear. – yume_chan Jan 17 '18 at 02:31
  • I see, so the `this.r` regex object remember the state / index. Thanks! – Abdillah Jan 17 '18 at 02:45
  • I would recommend to pass a string to `exec` though, not an integer to be stringified. – Bergi Jan 18 '18 at 16:20
  • use regex and now you have [two problems](https://meta.stackexchange.com/a/20842) – Aleksey Solovey Jan 29 '18 at 14:02
208

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:

enter image description here

Second attempt:

enter image description here

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.

mehulmpt
  • 15,861
  • 12
  • 48
  • 88
  • 52
    Honestly, this is the best answer. All the other answer require a deliberate attempt to do something deeply unintuitive. This answer actually reflects something that might happen in the real world - a race condition. – Tom Swirly Jan 17 '18 at 09:49
  • 36
    Not only that - I've actually seen this happen in the real world. Not with the exact condition in the question, but certainly with checking (a==1) at the start of a function and (a==2) later in the function, and having code hit both conditions. FYI, the first time I saw this happening was in a car engine controller, and we put coding standards in place. The second time was in a chaff and flare dispenser system for military aircraft, and on my *very first day at the company* I found this and fixed it, while the rest of the team were still discussing the problem. (Kudos level: high! :) – Graham Jan 17 '18 at 13:15
  • 41
    So, you've worked on "car engine controllers" and "chaff and flare dispenser systems" which are programmed in javascript with web workers? I don't think I'll be going outside again. – psaxton Jan 18 '18 at 21:55
  • 15
    @psaxton :) Of course not - but we have multi-threaded software with shared data. This is an anti-pattern for all multi-threaded software, not specific to Javascript or to web workers. It doesn't matter whether you're programming in assembly language, Brainf\*ck, Visual BASIC, C or Javascript - if you do this with shared data in a multi-threaded application, it ***will always*** fail. – Graham Jan 19 '18 at 11:24
  • 2
    @mehulmpt I wasn't aware that a web worker could mutate variables on the main thread. Can you provide some example code? – qntm Jan 20 '18 at 12:25
  • @qntm variable is not in the main thread. everything is accessing shared memory – mehulmpt Jan 20 '18 at 19:55
  • 2
    Uh, how do you access a *variable* through a SharedArrayBuffer? Even though multiple workers can share buffers, they cannot share variables. – Bergi Jan 23 '18 at 05:08
  • 1
    This isn’t possible (and is kind of why SharedArrayBuffer exists). – Ry- Jan 23 '18 at 06:12
  • @Bergi check the example above – mehulmpt Jan 23 '18 at 12:55
  • @qntm check the example above – mehulmpt Jan 23 '18 at 12:55
  • @mehulmpt In your current example you're testing `a[0] == 1 && a[0] == 2 && a[0] == 3`, not `a == 1 && a == 2 && a == 3`. That's not what the original question was asking for. Are you able to show an example with `a` instead of `a[0]`? – qntm Jan 23 '18 at 13:30
  • 4
    I think this is now an elaborate wrapper around @jontro's answer. – qntm Jan 23 '18 at 16:06
  • 1
    Sure. The wrapper is required just to access shared memory from a variable named "a". It is Shared ARRAY buffer, :) And numbers, which we're working on right now, are not held by reference, but values. So doing `a=array[0]` is copying the current value of `array[0]` to `a` which is unintended behavior. Hope that helps @qntm – mehulmpt Jan 23 '18 at 16:41
  • 2
    It seems there are really only 3 answers to the question: `toPrimitive`/`valueOf`/`toString`, a getter property in a `with` statement, or a getter on the global object. Everything else are just variations of the theme "how to make a function return different values at different times". – Bergi Jan 23 '18 at 19:05
  • Is there any way to make this work without SharedArrayBuffer? ["Note that SharedArrayBuffer was disabled by default in all major browsers on 5 January, 2018 in response to Spectre."](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) My hypothesis is that you'll get a success after fewer iterations if you keep looping the shared variable (1,2,3,1,2,3,1,2,3,1,...) rather than assign it a random number, like I do in my somewhat-related [multithreaded Java answer](https://stackoverflow.com/a/48383616/981744) – Erwin Bolwidt Jan 25 '18 at 01:49
  • 1
    @ErwinBolwidt SharedArrayBuffer is back – mehulmpt Sep 08 '18 at 10:28
  • Sorry but if it works once in 1e10 iterations it means it has a 0.000000001% chances of working - i.e., it does NOT work – gotofritz Jun 23 '20 at 23:01
  • @gotofritz looks like somebody never worked with high load systems – mehulmpt Sep 13 '20 at 15:00
196

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;
Object.defineProperty(window, 'a', {
  get: function() {
    return ++val;
  }
});
if (a == 1 && a == 2 && a == 3) {
  console.log('yay');
}

This answer abuses the implicit variables provided by the global scope in the execution context by defining a getter to retrieve the variable.

jontro
  • 10,241
  • 6
  • 46
  • 71
  • This assumes `a` is a property of `this` which it does not appear to be. If `a` was a local variable (which it looks like), then this would not work. – jfriend00 Jan 15 '18 at 20:43
  • 1
    @jfriend00 you mean if you placed var a; somewhere? – jontro Jan 15 '18 at 20:47
  • Yeah. Referencing `a == 1` implies than `a` is a variable somewhere, not a property of `this`. While there is an oddball place like globals where both could be true, generally, declaring a variable with `var a` or `let a` means there's no `this` that lets you access `a` as a property like you're code assumes. So, your code is apparently assuming some weird global variable thing. For example, your code does not work in node.js and not in strict mode inside a function. You should specify the exact circumstances where it works and probably explain why it works. Otherwise, it's misleading. – jfriend00 Jan 15 '18 at 21:11
  • @jfriend00 well sure. Not sure that it would add much more value in combination with the other already answers. Will update the answer – jontro Jan 15 '18 at 21:29
  • 15
    The question was, could this "ever" be true. And the answer is yes, and this is one of the scenarios where it might be true: `a` is not a local variable and is defined on the global scope with an incrementing getter. – Zac Delventhal Jan 17 '18 at 16:59
  • You could save the global variable `val` by doing `this.val = this.val || 0;` and using `this.val` instead. That way it would be self-contained. – Alvaro Montoro Jan 25 '18 at 15:28
147

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.)

(() => {
    "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.");
    }
})();
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
Patrick Dark
  • 2,187
  • 1
  • 20
  • 23
135

Alternatively, you could use a class for it and an instance for the check.

function A() {
    var value = 0;
    this.valueOf = function () { return ++value; };
}

var a = new A;

if (a == 1 && a == 2 && a == 3) {
    console.log('bingo!');
}

EDIT

Using ES6 classes it would look like this

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!');
}
Andrew Bone
  • 7,092
  • 2
  • 18
  • 33
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 5
    just `function A() {value = 0;` at the start? – Dave C Jan 17 '18 at 16:51
  • `valueOf` is being overridden, `this method is usually called automatically by JavaScript behind the scenes, and not explicitly in code` so when we compare the value it actually increments a.. – Danyal Sandeelo Jan 24 '19 at 09:27
130

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;
var a = 2;
var а = 3;
if(a == 1 && a == 2 && а == 3) {
    console.log("Why hello there!")
}

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
- 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: α,, 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.

  • 19
    ["Slight discrepancy"](https://i.stack.imgur.com/NPo2j.png) is not how I would call that. –  Jan 17 '18 at 00:17
  • 4
    @hvd Entirely depends on your font rendering. [This is what I see](https://i.stack.imgur.com/6POUG.png). – Draco18s no longer trusts SE Jan 17 '18 at 00:37
  • 1
    @Jake Yeah, the Full Width Latin lower case A isn't the greatest homoglyph (but the capital-letter variants are amazing). Generally though you only need two to get the desired effect. – Draco18s no longer trusts SE Jan 17 '18 at 01:32
  • 10
    You can also use unicode variant selector (U+FE00..U+FE0F). None of these are `a`: `a︀` `a︁` `a︂`. No more worrying about discrepancies. – Salman A Jan 19 '18 at 08:55
121

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

The above code is a short version (thanks to @Forivin for its note in 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;}

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 to if. In JavaScript we can not override keywords so I forced to use this way. It is a fake if, but it works for you in this case!


» C#

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

Live Demo

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ramin Bateni
  • 16,499
  • 9
  • 69
  • 98
  • `function if<200c> { }` how it is working why not working with `function if<123c>{}` – muthukumar selvaraj Jan 21 '18 at 18:16
  • @muthukumar, I used `\u200c` (ZERO WIDTH NON-JOINER) character in my answer, you want a `if` with `\u123c`? OK write `if` then press `Alt`, press `+` press `123c` release `Alt` it make this word» `ifሼ` – Ramin Bateni Jan 22 '18 at 00:29
  • @SaurabhChandraPatel, Yes KevinB answer is nice. My JS answer has trick, also I updated my answer with a C# version (It has no trick) ;) – Ramin Bateni Jan 22 '18 at 07:38
  • 61
    The javascript version is a true crime against humanity and the ability to do this, should be illegal by UN-conventions. I think it's about time we purge the world of all knowledge of javacript. – Clearer Jan 22 '18 at 10:24
  • 2
    The function declaration could be even shorter. `if‌=()=>!0` – Forivin Jan 23 '18 at 16:02
  • 7
    Why on earth did you use `document.write`? That's a surefire way not to get hired regardless of the rest of the answer. – Cerbrus Jan 23 '18 at 16:04
  • 4
    @Cerbrus, Thank you for your note. I wrote first my answer with `console.log` but I changed it to document.write. Really always I use `console.log` in my codes but here I just want show a text to users in StackOverflow code snippet box. So I wanted to show my message more beautiful than the message generated by `console.log`. Click the `Run Code Snippet` button on my answer and on other answers. The SO Code Snippet let me to use html and JS and CSS then I wanted to use it in my answer and make it nice. I think It has not any negative side effect and did not made my answer large or complected. – Ramin Bateni Jan 23 '18 at 17:11
  • 1
    @Clearer, If UN-Conventions could change the world effectively, then we should have a better world than this. We need somethings more than statement in UN and until that day I think we can use this Javascript trick of mine ;) – Ramin Bateni Jan 23 '18 at 19:01
  • @RAM Are you saying that the UN is largely irrelevant to the world as is? Blasphemy! – Clearer Jan 24 '18 at 07:19
  • 1
    @Clearer, I say our world is dark and one of its reasons is that one of the most important organisations in our world that named UN, is not effective as expected. The blasphemy is when we are insisting to be blindness while we can be brave-heart and open our eyes. – Ramin Bateni Jan 24 '18 at 10:27
  • What do you mean by *"with increase property value technic"* (it seems to be incomprehensible)? – Peter Mortensen Mar 21 '18 at 18:58
  • @PeterMortensen thank you for your question it was my selection. I meant the Technic that I used in C# version (**_increasing one unit to the value of a property after each time we get it_**). Many of the answers in this page such as the accepted answer used this way and I named it "_Increase property Technic_" in my answer. – Ramin Bateni Mar 22 '18 at 20:32
  • @PeterMortensen: Perhaps RAM not a native English speaker and means “_technique_” by “_technic_”, i.e. he means the technique of incrementing a property every time the value of `a` is taken.. – PJTraill Jan 09 '19 at 01:34
  • While earning full marks for deviousness, this does not actually answer the question, as the value of `(a== 1 && a ==2 && a==3)` is not used. – PJTraill Jan 09 '19 at 01:36
98

JavaScript

a == a +1

In JavaScript, there are no integers but only Numbers, 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 four consecutive integers:

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

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 ==:

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

Python

You can either define == for a new class:

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

or, if you're feeling adventurous, redefine the values of integers:

import ctypes

def deref(addr, typ):
    return ctypes.cast(addr, ctypes.POINTER(typ))

deref(id(2), ctypes.c_int)[6] = 1
deref(id(3), ctypes.c_int)[6] = 1
deref(id(4), ctypes.c_int)[6] = 1

print(1 == 2 == 3 == 4)
# True

It might segfault, depending on your system/interpreter.

The python console crashes with the above code, because 2 or 3 are probably used in the background. It works fine if you use less-common integers:

>>> import ctypes
>>> 
>>> def deref(addr, typ):
...     return ctypes.cast(addr, ctypes.POINTER(typ))
... 
>>> deref(id(12), ctypes.c_int)[6] = 11
>>> deref(id(13), ctypes.c_int)[6] = 11
>>> deref(id(14), ctypes.c_int)[6] = 11
>>> 
>>> print(11 == 12 == 13 == 14)
True

Java

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.");
        }
    }
}
Eric Duminil
  • 52,989
  • 9
  • 71
  • 124
  • 27
    @cᴏʟᴅsᴘᴇᴇᴅ: Java, Javascript, potayto, potahto :) There are enough good JS answers already. I just thought it would be interesting to show how it can be done in other languages, and possibly give JS developers some ideas. – Eric Duminil Jan 17 '18 at 17:16
  • 2
    @cᴏʟᴅsᴘᴇᴇᴅ: Updated with a JS example. – Eric Duminil Jan 17 '18 at 17:57
  • 1
    Why doesn't the Java version work with `Integer a = 42` (or does it)? As I understand autoboxing, `Integer a = 42; a == 1 && a == 2 && a == 3` should box all of the ints. Or does this unbox a for the comparisons? – CAD97 Jan 18 '18 at 23:16
  • @CAD97: `Integer == int` seems to result in unboxing. But using `Integer#equals(int)` forces autoboxing, so it works. Thanks for the comment! – Eric Duminil Jan 19 '18 at 08:06
  • @StephanBijzitter: Please explain. As far as I know, there are only `Numbers` in JS, which are basically like `double`s. They can look like integers and you can use them like integers, but they still aren't integers. I don't think `n == n + 1` can ever be true for integers in Java/Python/C/Ruby/... – Eric Duminil Jan 19 '18 at 09:02
  • @StephanBijzitter: So... what's your argument exactly? – Eric Duminil Jan 19 '18 at 15:03
  • There's nothing to argue about. They're either there or they're not, and they're there. – Stephan Bijzitter Jan 19 '18 at 15:44
  • @StephanBijzitter: "They're either there or they're not". Okay. So there's definitely no integer in JS. `1.0` might be displayed as `1`, it's still a float though. – Eric Duminil Jan 19 '18 at 16:17
  • You use max value but the right answer is using object prototype function declaration. – AmerllicA Jan 21 '18 at 07:14
  • @StephanBijzitter According to the specs, all numbers are required to act like double precision floating point decimals. However, you are correct that many browsers optimize and internally store numbers as integers when there is not the threat of overflow. – Jack G Jul 10 '18 at 20:44
81

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;
var ᅠ1 = a;
var ᅠ2 = a;
var ᅠ3 = a;
console.log( a ==ᅠ1 && a ==ᅠ2 && a ==ᅠ3 );

* 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;
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);
****/

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).

Salman A
  • 262,204
  • 82
  • 430
  • 521
74

Rule number one of interviews; never say impossible.

No need for hidden character trickery.

window.__defineGetter__( 'a', function(){
    if( typeof i !== 'number' ){
        // define i in the global namespace so that it's not lost after this function runs
        i = 0;
    }
    return ++i;
});

if( a == 1 && a == 2 && a == 3 ){
    console.log( 'Oh dear, what have we done?' );
}
MonkeyZeus
  • 20,375
  • 4
  • 36
  • 77
  • 7
    Ouch. `__defineGetter__` is actually not part of the js language, just an ugly version of `defineProperty`. `typeof` is not a function and this undeclared `i` is just awful. Still seems to be worth 40 upvotes :/ – Jonas Wilms Jan 17 '18 at 16:03
  • 6
    @JonasW. 41 upvotes :-) I am aware that `__defineGetter__` is deprecated per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineGetter__ but it clearly executes in my FireFox v 57.0.4 so I opted to show this instead of `defineProperty()` because legacy code is real and cannot be ignored. Regardless of the ugliness, declaring `i` in the way I did is a well known/documented behavior. Maybe I was just in a PCG mood ¯\\_(ツ)_/¯ – MonkeyZeus Jan 17 '18 at 16:13
  • "Rule number one of interviews; never say impossible.", If everything is possible, then it's possible for something to be impossible, so the premise is false – Piyin Jan 10 '23 at 15:25
  • @Piyin Being technically correct is the worst kind of correct and striving to be the "ackchyually" guy is not a respected accolade. Keep that in mind when dealing with anyone that's not as pedantic as you are. "never say impossible" is a reflection of character which reveals whether you are a closed-minded or open-minded person. It is not a statement meant to reflect philosophical completeness. – MonkeyZeus Jan 10 '23 at 16:29
  • @MonkeyZeus Why is it the worst kind of correct? How does the phrase reveals that? It's not about philosophical completeness, it's about a false premise. – Piyin Jan 11 '23 at 13:20
67

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.

Frank W. Zammetti
  • 1,231
  • 1
  • 11
  • 19
  • 1
    So, would you penalize someone who takes your question in good faith, and is so knowledgable that they can actually answer it correctly? I'd be pretty upset if someone did that to me. Not sure whether that's your intent, but if it's not, you might want to edit your answer to make it clear. – Don Hatch Jan 17 '18 at 01:46
  • 13
    The question (or all interview questions) is probably to test the candidates willingness to think about a problem, especially ones that are "apparently obvious", like this one. Someone who refuses to think because they believe they "know" the answer is not a good hire. – Shammoo Jan 17 '18 at 02:40
  • 5
    @Don Hatch No, I wouldn't penalize them if they answered in good faith and especially if they gave a correct answer like those others have shown... but I would then ask a follow-up to try and probe whether they think it's a good way to write code or not. Being knowledgeable and being able to come up with a "correct" answer is only part of being a good developer. Far more important for a "professional" developer is writing code that is understandable and maintainable down the road, often times by less capable developers. Overly clever developers are pretty much as bad as incapable ones IME. – Frank W. Zammetti Jan 17 '18 at 06:51
  • 17
    This doesn't answer the question. – TylerH Jan 17 '18 at 15:44
  • 6
    The sad thing about this answer is that a 1rep user answered that yesterday and got 2 downvotes causing him to delete this question. – Jonas Wilms Jan 17 '18 at 15:53
  • @TylerH Since this gives an intelligent way to answer the interview question and OP was asking about how they should have answered that question, I think that this is a perfectly valid answer. It probably shouldn't be the accepted answer, but it does add something useful (hence the many upvotes, including mine). – John Coleman Jan 18 '18 at 18:21
  • 8
    @JohnColeman the question asks how the code could evaluate to true. It doesn't ask the reasons the interviewer proposed the question in the first place. This answer doesn't even attempt to address the question being asked, and instead focuses entirely on a "what I would do" version of an attempt at guessing what the interviewer's purpose was. If that were the question asked, it would be way too broad. Therefore this answer doesn't belong here or anywhere on the site. – TylerH Jan 18 '18 at 18:25
  • 2
    I don't fundamentally disagree with TylerH in that my answer does not directly address the question asked. But at the same time, as John Coleman says, there is arguably some value to it. I would argue that if an answer is deemed meritorious, even if tangential, then it offers some benefit to the SO community and thus belongs, and ultimately votes are the arbiter of what has merit and what does or doesn't belong. I just wanted to explain why I'm not going to delete the answer (no one directly suggested I should, but it's implied). – Frank W. Zammetti Jan 19 '18 at 19:58
  • @TylerH the question asks _if_ the code could evaluate to true, not _how_. – Phil Jan 21 '18 at 09:13
  • 2
    @Phil Actually "I'm still trying to find the answer" implies pretty heavily that they don't just want a 'yes or no' answer, but an explanation of how. What's *not* implied is "why". – TylerH Jan 21 '18 at 17:42
  • 2
    In other words, you never maintain code you didn't write yourself? Good luck with that attitude in interviews. – Alfred Armstrong Jan 23 '18 at 17:05
  • @Shammoo, now tell me HONESTLY, how many times you'd use any of those answers in production code? Whoever DOES think about this except for amusement is "not a good hire". – Oleg V. Volkov Jan 25 '18 at 14:39
  • 1
    @OlegV.Volkov I use thinking to produce most (hopefully) of my production code. Anytime I see myself or anyone run with the first idea without further thought, the solution is usually poor and takes a very long time to construct. – Shammoo Jan 26 '18 at 17:47
43

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:

  1. 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)).

  2. 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.

  3. 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:

  • Side-effects can get really nasty and that a well-designed program should be free from unwanted side-effects.
  • Multi-threading and mutable state can be problematic.
  • Not doing character encoding and string processing right can lead to nasty bugs.

1 For example, you can find an example in a totally different programming language (C#) exhibiting a side-effect (an obvious one) here.

Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
  • 1
    Then, the question becomes way too broad. Different languages can implement this with varying degrees of ease. The question has gained so much traction because it is a JS specific Q&A, but that's just my 2c. – cs95 Jan 17 '18 at 14:51
  • 1
    the causes are different C# and javascript so this answer is not legit. – Edwin Jan 17 '18 at 15:01
  • 3
    @Edwin: The causes are exactly the same: Unicode fiddling with similar-looking glyphs or space characters, race conditions, or side-effects of the comparison operation (the latter being shown in my example). – Dirk Vollmar Jan 17 '18 at 15:03
  • 2
    @cᴏʟᴅsᴘᴇᴇᴅ: Sometimes looking at things from a broader angle helps see the actual problem. – Dirk Vollmar Jan 17 '18 at 15:17
  • what I've meant is that your original answer (and now the code part) doesn't address exactly this question. However, by re-editing your answer I agree with you that other froms of the problem can rise in js or other languages. – Edwin Jan 17 '18 at 16:00
  • i see none of theese three points to actually match. there are no race conditions in javascript. encoding does not make a difference. side-effects.. well if you consider the fact each access to a variable queries it from the stack.. yes. but still i'd call it intentional to get it working like that. – GottZ Jan 18 '18 at 18:03
  • 1
    @GottZ: Note that [race conditions do not require multiple threads](https://medium.com/@slavik57/async-race-conditions-in-javascript-526f6ed80665), encoding [makes a difference](https://stackoverflow.com/a/48274520/40347) and [side-effects are certainly possible in JS](https://stackoverflow.com/a/48270314/40347). The interview question requires intentionally written code, but you should see it as an example demonstrating what is possible if devs don't pay attention to these details. – Dirk Vollmar Jan 20 '18 at 14:23
  • 3
    I wish this answer could be tagged to this question in some "meta" way. After reading all of the answers above it, I was left feeling like JS has *so* many holes, but you just summed up all of the answers in one go. And you did it in a way that makes this into a stellar interview question (if the language-specific tag is removed) in my opinion. Bravo! – KCE Jan 22 '18 at 09:59
  • Doesn't asynchronicity use different threads under the hood or is this a misconception? – Agi Hammerthief Jan 25 '18 at 13:00
  • 1
    @AgiHammerthief: No, this is a misconception, see [Does async programming mean multi-threading?](https://stackoverflow.com/questions/8963209/does-async-programming-mean-multi-threading) – Dirk Vollmar Jan 25 '18 at 13:07
40

Here's another variation, using an array to pop off whatever values you want.

const a = {
  n: [3,2,1],
  toString: function () {
    return a.n.pop();
  }
}

if(a == 1 && a == 2 && a == 3) {
  console.log('Yes');
}
Théophile
  • 1,032
  • 10
  • 16
33

Okay, 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!');
}
Durga
  • 15,263
  • 2
  • 28
  • 52
BaggersIO
  • 838
  • 7
  • 10
  • You say hack, but I'm pretty sure this is the use case of generators... :) (well, except that this relies on `this` being the window object) – Cody G Jan 23 '18 at 16:30
30

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:

  1. We create a target object, { i: 0 }, where the i property is our counter
  2. We create a Proxy for the target object and assign it to a
  3. For each a == comparison, a's type is coerced to a primitive value
  4. This type coercion results in calling a[Symbol.toPrimitive]() internally
  5. The Proxy intercepts getting the a[Symbol.toPrimitive] function using the "get handler"
  6. The Proxy's "get handler" checks that the property being gotten is 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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
IceCreamYou
  • 1,852
  • 14
  • 25
  • 3
    There isn’t a point in using a proxy for this, though – defining `Symbol.toPrimitive` in the same way on an object would work just as well. – Ry- Jan 23 '18 at 06:13
26

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;
}
Tim
  • 41,901
  • 18
  • 127
  • 145
  • 28
    I don't think it's possible in *every* programming language. Not all languages have preprocessors, for example. For that matter, not all languages use `&&` for logical "and". – Keith Thompson Jan 16 '18 at 20:05
  • 3
    I found a way that works both in [Python](https://trinket.io/python3/7fc8db9cf1) and [C++](https://codepad.remoteinterview.io/UZTDNYBOSN) which uses operator overloading. – Donald Duck Jan 16 '18 at 20:35
  • 1
    Most languages will allow you to overwrite the operator – LukeS Jan 16 '18 at 21:29
  • 7
    And you can do it in Java by using reflection and messing up the integer cache. – CAD97 Jan 16 '18 at 23:37
  • 3
    I very much doubt this works in C, given the use of `std::cout` – Tas Jan 16 '18 at 23:46
  • 2
    @tas: I know. You should change it to printf. But you got the idea, I think. – Gustavo Rodríguez Jan 17 '18 at 00:45
  • 8
    Can't do it in languages that woudn't support mutation in that spot, e.g. nothing comparable is available in haskell – Jason Carr Jan 17 '18 at 05:44
  • 1
    I'm not exactly an expert in Haskell, but wouldn't this be possible with an appropriate type class and appropriate overload for the == operator? Gustavo's example is certainly clever, but I would expect most languages (which don't have a processor) would do it with operator overloading rather than symbol redefinition. – GrandOpener Jan 17 '18 at 10:25
  • @CAD97: I tried it. It works with `Integer.valueOf(1)`. Can it also work with primitive `int`s? – Eric Duminil Jan 17 '18 at 10:27
  • @EricDuminil https://codegolf.stackexchange.com/a/28818/51825 (make `a` of type `Integer` and it should work) – CAD97 Jan 17 '18 at 12:18
  • @CAD97: I don't think so. The linked answer is really interesting, but it still cheats a bit. It solves `Integer.valueOf(2 + 2) == 5` but not `2 + 2 == 5`. If I set `a` to an Integer, it can still be only equal to one `int`, not three distinct ones. – Eric Duminil Jan 17 '18 at 13:46
  • 4
    The question is asking about JavaScript, not C++. – Uyghur Lives Matter Jan 17 '18 at 14:29
  • @cpburnz As I said, I'm talking about the first part of the question. I think the second part has been sufficiently answered. – Gustavo Rodríguez Jan 17 '18 at 15:36
  • 3
    not only does the question explicitly mention javascript, it is also tagged as such. C/C++ is completely irrelevant – Tim Jan 17 '18 at 15:40
  • 2
    It is not possible in ML. The equality testing operator (`op=`) is hardwired to mean equality, and you can't redefine it to mean anything else. Moreover, the language makes a distinction between values and mutable cells containing values. You can test mutable cells for equality, but that compares the object identities of the cells, not their contents. – isekaijin Jan 18 '18 at 03:44
  • @Tim Castelijns: please check my answer to cpburnz. Also seems others answers got a lot of upvotes talking about the first part of the question, including examples in Java, C#, etc. Finally, I'm sorry but irrelevant it's a legal term, used in court rooms. There is no such thing in programming, same way nothing is impossible as others answers prove. Meaning, in programming everything is relevant and possible. – Gustavo Rodríguez Jan 22 '18 at 11:03
  • 3
    @GustavoRodríguez *Also seems others answers got a lot of upvotes talking about the first part of the question, including examples in Java, C#* - yes don't worry, I downvoted all of them. If you think "irrelevant" is only used in court rooms, you might want to look up what the word means. – Tim Jan 22 '18 at 11:07
26

Same, but different, but still same (can be "tested" multiple 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!');
}

My idea started from how Number object type equation works.

Preda7or
  • 328
  • 2
  • 7
25

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Omar Alshaker
  • 879
  • 9
  • 22
24

I think this is the minimal code to implement it:

i=0,a={valueOf:()=>++i}

if (a == 1 && a == 2 && a == 3) {
  console.log('Mind === Blown');
}

Creating a dummy object with a custom valueOf that increments a global variable i on each call. 23 characters!

gafi
  • 12,113
  • 2
  • 30
  • 32
15

This one uses the defineProperty with a nice side-effect causing global variable!

var _a = 1

Object.defineProperty(this, "a", {
  "get": () => {
    return _a++;
  },
  configurable: true
});

console.log(a)
console.log(a)
console.log(a)
Ben Aubin
  • 5,542
  • 2
  • 34
  • 54
3

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.

Jonathan Kuhl
  • 699
  • 9
  • 23
0

As we already know that the secret of loose equality operator (==) will try to convert both values to a common type. As a result, some functions will be invoked.

ToPrimitive(A) attempts to convert its object argument to a primitive value, by invoking varying sequences of A.toString and A.valueOf methods on A.

So as other answers using Symbol.toPrimitive, .toString, .valueOf from integer. I would suggest the solution using an array with Array.pop like this.

let a = { array: [3, 2, 1], toString: () => a.array.pop() };

if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}

In this way, we can work with text like this

let a = { array: ["World", "Hello"], toString: () => a.array.pop() };

if(a == "Hello" && a == "World") {
  console.log('Hello World!');
}
Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56
0

If we use JavaScript's property of converting objects to primitive values and its getter functions, it can be possible.

const a = {
    value: 0,
    valueOf: function() { 
        return this.value += 1; 
    }
}

if (a == 1 && a == 2 && a == 3) {
  console.log('it can')
}
rjanjic
  • 2,640
  • 1
  • 15
  • 13
-6

Yes, you can Do that, see the following JavaScript code:

let a = 0 // Create a variable and give it a value
    
if( a !== 1 && a !== 2 && a !== 3 )
  {
    console.log("true")
  }

Explanation of the solution:

Simply , we add the not equal sign before the == sign so that we tell the language that these values are not equal to the value in the variable

SecretAgentMan
  • 2,856
  • 7
  • 21
  • 41
eror programs
  • 51
  • 1
  • 8