15 02 2013
Why isNaN and Number is not enough to cast string to a number
Recently I was doing string casting to a number and while you think it’s simple as it is, it took me a bit to make it fully functional.
My first approach was to use a Number constructor for casting, which would return number or NaN if value was not parsable to the number. But for empty strings, boolean values and null values, this approach gave unsatisfying result.
Number("123zork") // NaN Number("")) // 0 Number(" ")) // 0 Number(null) // 0 Number(false) // 0 Number(true) // 1
Then, I decided to use isNaN to check the string before applying Number constructor. But isNaN was for no help either. It looks like underneath isNaN uses Number implementation and gives the same result as above 🙁
isNaN("123zork")) // true isNaN("")) // false isNaN(" ")) // false isNaN(0)) // false isNaN(null) // false isNaN(false) // false
After my isNaN attempt faild my next idea was to use parseFloat. But problem with parseFloat is that strings like “123aa” are parsed into 123.
parseFloat('123zork') // 123 parseFloat("")) // NaN parseFloat(" ")) // NaN parseFloat(null) // NaN parseFloat(false) // NaN parseFloat(true) // NaN parseFloat('11111') // 11111 parseFloat('1.2') // 1.2
The one solution which is left, was to cast value to the String by using String constructor and then pass it to the Number constructor, which would make boolean and null in a string representation and would result in NaN value for bad strings. Great.
Number(String('123zork') // NaN Number(String("")) // 0 Number(String(null)); // NaN Number(String(false)); // NaN Number(String('1.2')) // 1.2
Of course empty string is a breaker here, so time test string before using for emptiness:
Number(String.trim(value) === '' ? NaN : String(value))
Related StackOverflow question: