JavaScript never ceases to surprise me. This time, a friend shared the following riddle in the JavaScript Israel community:
Which value of x
will cause the following statement to be true
?
!x && (x !== false) && (x !== 0) && (x !== '') && (x !== null) && (x !== undefined)
Basically, we want to find a value that is falsy in JavaScript (in other words, !x
is true), but is not false
, null
, undefined
, zero or the empty string.
Take a moment to think of an answer. Then, scroll down for my answer and other answers suggested by the community.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
My Answer
My approach was to make x
evaluate to a different value each time, so it will be falsy when !x
is evaluated, but will pass all the other tests.
Thus, I defined a getter for x on the window
object, incrementing the returned value upon each call:
var counter = 0;
Object.defineProperty(window, 'x', { get: () => counter++ });
Since x
starts with zero and increments on each read, the original expression becomes:
!0 && (1 !== false) && (2 !== 0) && (3 !== '') && (4 !== null) && (5 !== undefined)
which evaluates to true!
Even More Answers
While I was typing my answer, someone has already found a very simple answer: x should be NaN
. This value is falsy, and is indeed not equal to any of the the other values in the expression. You can also verify this by looking at the definition of toBoolean in the ECMAScript standard.
Another answer, which really surprised me, was document.all
. If you are curious to know why document.all
is indeed falsy, check out this StackOverflow answer. Legacy reasons, amazing!
Finally, the answer that the original author of this riddle was looking for, is BigInt(0)
. If you haven't heard of this before, don't worry - it's still not an official part of the JavaScript language, but will probably be soon, as part of the BigInt proposal. If you are interested, MDN has a pretty good documentation about BigInt.
What I love about this riddle, is how diverse the solutions are: one exploits the dynamic nature of JavaScript using Object.defineProperty
, another solution uses legacy feature (document.all), while the BigInt
solution uses a feature which has not yet introduced into the language (but is already available in Chrome). Pure fun, isn't it?
Top comments (1)
Thanks!!
this is a really great one...