String(new Date(NaN))
Written , a 2 minute read
I'm glad that I didn't ever care too much for ECMAScript 5 or Internet Explorer. I started with web development around 2015 and most tech that classmates used around me felt clunky and unnecessary for me. I was having way too much with ECMAScript 6 features, CSS3 and HTML5.
This fresh look (and not working with enterprise JavaScript for next 4 years) meant that I missed all that noise of jQuery, Bootstrap and pollyfills. The only thing that seemed interesting to me at the time was CoffeeScript since I didn't know Python back then and this kind of syntax felt fresh and interesting.
While reading "The State of ES5 on the Web by Philip Walton, I realized how lucky I was to skip all of that. Especially when I noticed how weird some of the pollyfills were.
String(new Date(NaN))
behaviour was left to implementation, as stated in ECMAScript 5 specification:
15.9.5.2 Date.prototype.toString ( )
This function returns a String value. The contents of the String are implementation-dependent, but are intended to represent the Date in the current time zone in a convenient, human-readable form.
ECMAScript 6 defined the output,
by delegation to the ToDateString(tv)
abstract operation:
21.4.4.41.4 ToDateString ( tv )
The abstract operation ToDateString takes argument tv (an integral Number or NaN) and returns a String. It performs the following steps when called:
- If tv is NaN, return "Invalid Date".
- Let t be LocalTime(tv).
- Return the string-concatenation of DateString(t), the code unit 0x0020 (SPACE), TimeString(t), and TimeZoneString(tv).
The first step of this algorithm lead to this lovely pollyfill inside core-js (simplified by me):
if (String(new Date(NaN)) !== 'Invalid Date') {
var toString = Date.prototype.toString;
Date.prototype.toString = function() {
var value = this.getTime();
return value === value ? toString.call(this) : 'Invalid Date';
});
}
Which utilizes IEEE-754 lack of equality between NaNs (shouldn't this return undefined instead of false since this comparison is unordered?) to test for their presence (with value === value
),
which is recommended in ECMAScript 5 standard:
15.1.2.4 isNaN (number)
Returns true if the argument coerces to NaN, and otherwise returns false.
NOTE
A reliable way for ECMAScript code to test if a value X is a NaN is an expression of the form X !== X. The result will be true if and only if X is a NaN.
Why
isNaN
wasn't implemented as reliable way to detect NaNs is beyond me (current standard recommends the same by the way).