Option C. The value
NaN
compares unequal to every value, even itself. This breaks one of the rules of what equality even means (that every value must be equal to itself, the “reflexivity” axiom). It is for this reason (among others,equality“partial” equivalence between values of different types? 🤮) Rust needed to havePartialEq
. See IEEE 754 for more details.Why
typeof null
is"object"
? Because it is defined so: https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-typeof-operator5. If
val
isnull
, return"object"
.As for the rationale behind the choice, it might have something to do with “Prototypal inherience” the language has. https://tc39.es/ecma262/multipage/overview.html#sec-objects
Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s “prototype” property. Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain.
We can understand this to mean that prototype chains are
null
terminated ;)For example:
> Object.getPrototypeOf({}) === Object.prototype true > Object.getPrototypeOf(Object.getPrototypeOf({})) null > Object.getPrototypeOf(null) TypeError: not an object
Uhh…
Now, let’s go to some abstract algebra. All good (closed) binary operations we deal with have an identity or neutral value. For example: addition has 0, multiplication has 1, boolean
and
hastrue
, booleanor
orxor
hasfalse
. Performing these operations with the neutral value does not change the other operand: for example,x + 0 == x
,a * 1 == a
,true && b == b
and so on. If you admitmin
andmax
as operators, you can see why ∞ and -∞ are the neutral values, respectively:min(∞, x) == x
andmax(-∞, y) == y
for every (real) value of x and y. Observe howArray.prototype.reduce
works (with its second argument) for inspiration on why and how all this matters: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduceFor mathematicians: closed, because the operators are maps
S × S →S
, to exclude<
,etc. as they map to
Bool
. Oh, they are relations, bla bla … real numbers, we don’t want to deal with other total orders here, there should be some way to call orders that have both top and bottom values, complex numbers don’t have orders (usual ones, are there unusual ones?), bla bla blaAs for the last one, sigh… https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal
Oh, that
!
s in there aren’t booleannot
… they are… (looks it up) argh, read it yourself https://tc39.es/ecma262/multipage/notational-conventions.html#sec-returnifabrupt-shorthandsdeleted by creator
I love the two lonely downvotes on this.
Merging the upvotes and downvotes is the best option
nah, it’s more fun this way.
I’m no expert and I know that javascript is full of wtf moments, but please… Let it be B
It’s not gong to be B, it’s it.
C, because yes.
I’d say C too because that’s the only one that would be True in a normal programming language and this is javascript so…
probably not true in most other langauges. although I’m not well versed in the way numbers are represented in code and what makes a number “NaN”, something tells me the technical implications of that would be quite bad in a production environment.
the definitive way to check for NaN in JS would probably be something like
// with `num` being an unknown value // Convert value to a number const res = Number(num); /* * First check if the number is 0, since 0 is a falsy * value in JS, and if it isn't, `NaN` is the only other * falsy number value */ const isNaN = res !== 0 && !res;
Another way to check whether a number is
NaN
:const isNaN = res !== res;
As
NaN
is the only value out there that is not equal to itself. See my other comment on this post for more: https://programming.dev/comment/17221245This comparison should work in every programming language out there that implements/respects/uses IEEE 754 floating point numbers.