I'm just creating a function that will JSON.stringify
an input but also detecting NaN
on number inputs, but don't want to use typeof
because of reasons stated below. The input could be either a number
, boolean
or string
. Nothing more.
I've reached the situation where NaN !== NaN
, so:
if (input !== input || input === Infinity || input === -Infinity) {
output = input.toString();
} else {
output = JSON.stringify(input);
}
I'm doing it this way because JSON.stringify()
returns "null"
when the value is NaN
or Infinity
.
I know that with typeof
and toString()
this is pretty easy to achieve, but some performance tests shows that typeof
under IE11 is really slow (4-5 times slower than JSON.stringify()
under our situation), and we need to focus on IE11 here.
I would like to know if there are more cases where val !== val
.
Here you have a performance test: https://jsperf.com/typeof-vs-nan-nan2 Not used the SO one because seems that they run the codes server side, as there IE performance is as good as elsewhere. Impossibru thing.
Local test is:
var mockdata = [];
function notToJson(val) {
return val !== val || val === Infinity || val === -Infinity;
}
for (var i = 0; i < 500000; i++) {
var n = Math.floor(Math.random()*1000000);
if (Math.random()>0.5) {
n = n.toString();
} else if (Math.random()>0.5) {
if (Math.random()>0.5) {
n = NaN;
} else {
if (Math.random()>0.5) {
n = Infinity;
} else {
n = -Infinity;
}
}
}
mockdata.push(n);
}
console.time("typeof");
for (i = 0; i < 500000; i++) {
var res = typeof mockdata[i] === "string";
}
console.timeEnd("typeof");
console.time("notToJson");
for (i = 0; i < 500000; i++) {
res = notToJson(mockdata[i]);
}
console.timeEnd("notToJson");
console.time("toString");
for (i = 0; i < 500000; i++) {
res = mockdata[i].toString();
}
console.timeEnd("toString");
console.time("JSON.stringify");
for (i = 0; i < 500000; i++) {
res = JSON.stringify(mockdata[i]);
}
console.timeEnd("JSON.stringify");
console.time("Full typeof");
for (i = 0; i < 500000; i++) {
res = typeof mockdata[i]==="string"?JSON.stringify(mockdata[i]):mockdata[i].toString();
}
console.timeEnd("Full typeof");
console.time("Full notToJson");
for (i = 0; i < 500000; i++) {
res = notToJson(mockdata[i])?mockdata[i].toString():JSON.stringify(mockdata[i]);
}
console.timeEnd("Full notToJson");
Chrome output is:
But IE11 output is:
I've noticed that the less strings mockdata
has, the performance of typeof
is noticeably increased (Talking about IE11).