(a==1 && a==2 && a==3) true? JavaScript Magic

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: The Problem That Blew Up Stack Overflow

\n\n

Imagine this: you're in an interview, and the interviewer asks with a sly smile: "Can the expression a == 1 && a == 2 && a == 3 ever return true?". Your first reaction — "Of course not! One variable cannot simultaneously equal three different numbers."

\n\n

However, if you know JavaScript a little deeper, you know: in this language, the most unexpected things are possible. This question gathered thousands of views on Stack Overflow and became a classic for testing understanding of type coercion, getters, and object wrappers in JS.

\n\n

In this article, we will not only prove that this is possible but also break down 5 different ways to make (a==1 && a==2 && a==3) return true. You will learn how loose comparison (==) works, how it differs from strict comparison (===), and how you can control it.

\n\n

This article will be useful both for beginners who want to understand JavaScript more deeply, and for experienced developers preparing for an interview. Let's go!

\n\n

Method #1: The Magic of valueOf (Most Popular)

\n\n

The most elegant and frequently cited way is to use a custom object with an overridden valueOf method. In JavaScript, when you compare an object with a primitive using ==, the engine automatically calls valueOf() (or toString()) to convert the object to a primitive.

\n\n

We will create a counter object that increments its value by 1 each time valueOf is called.

\n\n
const a = {\n  value: 1,\n  valueOf() {\n    return this.value++;\n  }\n};\n\nconsole.log(a == 1 && a == 2 && a == 3); // true
\n\n

How it works:

\n
    \n
  • On the first comparison a == 1, valueOf() is called, returns 1, and value increments to 2.
  • \n
  • On the second comparison a == 2, valueOf() is called again, returns 2, value becomes 3.
  • \n
  • The third comparison a == 3 completes the chain successfully.
  • \n
\n\n

This is a perfect example of type coercion in action. It is this mechanism that makes JavaScript both a flexible and a dangerous language.

\n\n

Method #2: toString — The Twin of valueOf

\n\n

If you override toString instead of valueOf, the result will be the same. JavaScript can use either of these methods for object-to-primitive conversion during loose comparison.

\n\n
const a = {\n  value: 1,\n  toString() {\n    return this.value++;\n  }\n};\n\nconsole.log(a == 1 && a == 2 && a == 3); // true
\n\n

The difference is subtle: valueOf has priority for numeric comparisons, while toString has priority for string comparisons. But in our case, both work perfectly.

\n\n

Method #3: Getters in the Global Scope

\n\n

Many people don't even realize that global variables in JavaScript are actually properties of the global object (window in browsers, global in Node.js). And properties can be defined using getters.

\n\n

We can define a getter for the variable a directly on the global object:

\n\n
let value = 1;\nObject.defineProperty(window, 'a', {\n  get() {\n    return value++;\n  }\n});\n\nconsole.log(a == 1 && a == 2 && a == 3); // true
\n\n

This method is particularly interesting because a behaves like a regular variable, although it is actually a property with a getter. Every time you access a, the getter returns a new value.

\n\n

Note: This code works in the browser environment. In Node.js, you would use global instead of window.

Blogs

Book Recommendations