From the perspective of this specification, the word “is” is used to compare two values for equality, as in “If bool is true, then ...”, and the word “contains” is used to search for a value inside lists using equality comparisons, as in "If list contains a Record r such that r.[[Foo]] is true, then ...". The specification identity of values determines the result of these comparisons and is axiomatic in this specification.
From the perspective of the ECMAScript language, language values are compared for equality using the SameValue abstract operation and the abstract operations it transitively calls. The algorithms of these comparison abstract operations determine language identity of ECMAScript language values.
and then look at the algorithm for SameValue, we see that its first line is:
If SameType(x, y) is false, return false.
That is, the type will be checked again.
The question is:
why does the Number.isNaN algorithm have this redundant type check in the first step? If in the second step, the "is" construct also performs a type check.
It’s true that you could drop step 1 from the isNaN algorithm and it would behave the same. I suspect it’s there to help the reader understand that non-Numbers simply return false (rather than being converted to a Number which is then checked for being NaN). See the Note after the algorithm.
(Of course, any conversion to a Number would have to be explicit in the algorithm, so you could say that the lack of such explicit conversion should suffice to tell the reader that non-Numbers aren’t converted. And yeah, that’s true too.)
But if the algorithm is a single comparison that says “If number is NaN, return true”, it would still be well-formed because “is” is well-defined for different data types.
I am not disputing that NaN is of type Number. That is established by the specification. What I am asking is: why does the algorithm for Number.isNaN perform a type check for Number in the first step, when in the second step this check is performed again?
In the first step, the type is explicitly checked.
In the second step, the construct “is”—which,as we have established above, works according to the SameValue algorithm—also checks the type of the value being compared, namely NaN.
SameValue ( x, y )
If SameType(x, y) is false, return false.
[…]
Which(NaN) is a number. So we end up with two consecutive checks for the same thing.
The question is: why explicitly prescribe a type check for Number in the first step, if in the second step this check is performed just the same?
Or, in other words, if we remove the first step from the Number.isNaN algorithm, it will change NOTHING. There is not a single situation in which the first step would affect the execution of the algorithm.
Because the second step, in addition to comparing the two values, also checks their type.
That is, if the algorithm were written as follows, absolutely nothing would change: Number.isNaN ( number )
If number is NaN, return true.
Otherwise, return false.
Or am I mistaken somewhere, and the first step actually does make a difference?
Step 2. most certainly does not use the SameValue algorithm, because that would lead to infinite recursion. When both arguments are numbers, it goes to Number::sameValue, which uses the exact same wording:
If x is NaN and y is NaN, return true.
“x is NaN” does not describe comparing two values, because there’s no single NaN value. The expression is more akin to “x is negative”, it describes a property. Or set membership, as in “x is one of many invalid values of type number”.
See 6.1.6.1 The Number Type: “… the 9,007,199,254,740,990 (that is, 2**53 - 2) distinct NaN values of the IEEE Standard are represented in ECMAScript as a single special NaN value.” So there are many NaN value in IEEE 754, but there is a single NaN value in ECMAScript, and “x is NaN” is comparing two values.
Thanks for the clarification. Though I think the spec is fairly confusing when it defines a “single special NaN value” and two sentences later says “all NaN values are indistinguishable from each other.” With the bolded NaN that’s supposed to mean the singular value.
Also the same “all NaN values” wording appears in the comment under SameValue algorithm, which is where I got the assumption that it’s just like IEEE from.