Type casting

There are only a hand full of types in JavaScript. Many operations implicitly convert one of the few types into another, in ways that can be unpredictable. One way to handle that uncertainty is to learn every single possible rule and combination, another is to convert the types explicitly on our own, so we don't get surprised. We call that conversion type casting, and it helps us avoid type confusion, which is one of the JavaScript Common Pitfalls.

We're going to concentrate on converting to strings and numbers, since they seem to come up the most often.

There are a handful of reliable ways to convert to a string. Concatenating with an existing string, calling the `String` constructor function (without new) on an item, calling .toString (on items that exist), and for a slightly different string representation, JSON.stringify.

var manyTypes = [ undefined , null , 1 , 'Foo' , {a:'b'} , ['c', 'd'] , /a/ , function () {} , new Date() ] var conversions = manyTypes.map(function (a) { return ( [ ''+a , String(a) , a ? a.toString() : 'N/A' , JSON.stringify(a) ] ) }) console.log(conversions)

Which gives us the output:

[ [ 'undefined', 'undefined', 'N/A', undefined ], [ 'null', 'null', 'N/A', 'null' ], [ '1', '1', '1', '1' ], [ 'Foo', 'Foo', 'Foo', '"Foo"' ], [ '[object Object]', '[object Object]', '[object Object]', '{"a":"b"}' ], [ 'c,d', 'c,d', 'c,d', '["c","d"]' ], [ '/a/', '/a/', '/a/', '{}' ], [ 'function () {}', 'function () {}', 'function () {}', undefined ], [ 'Fri May 29 2015 22:43:53 GMT-0700 (PDT)', 'Fri May 29 2015 22:43:53 GMT-0700 (PDT)', 'Fri May 29 2015 22:43:53 GMT-0700 (PDT)', '"2015-05-30T05:43:53.206Z"' ] ]

The first three always give us the same output, except we can't directly call .toString from null or undefined. JSON.stringify gives us interesting results for the object, but it doesn't actually give us a string for undefined or the function, instead returning undefined! So, if we don't know what we're getting in, and we want to be sure it's a string going out, concat it with an exiting string (or empty string literal), or call the String function on it. Just remember not to use new String, that does something similar, but broken.

Infact, to avoid that, stick with the ''+wantsToBeAString. On to numbers.

var manyTypes = [ null , true , 1000 , '999aaa' , '1234' , new Date() ] var conversions = manyTypes.map(function (a) { return ( [ +a , Number(a) , parseFloat(a) , a ? a.valueOf() : 'N/A' ] ) }) console.log(conversions)

Which results in:

[ [ 0, 0, NaN, 'N/A' ], [ 1, 1, NaN, true ], [ 1000, 1000, 1000, 1000 ], [ NaN, NaN, 999, '999aaa' ], [ 1234, 1234, 1234, '1234' ], [ 1432965276619, 1432965276619, NaN, 1432965276619 ] ]

This is a much sadder looking set of results. At least the unary `+` operator and the Number function give us the same results, and they are all numbers (yes, NaN is a number). parseFloat also gives us all numbers, and it makes better sense of the string that is letters followed by numbers, but it fails at null, true, and the date object. .valueOf is intended to give us the value of an object, and is what gets called on objects for math operations. But it doesn't work well with most of samples other than Date.

So it really comes down to the unary +, and parseFloat. If you want to convert strings that start with numbers and then may do something else, use parseFloat, but if you want to get nonNaN answers for oddball values (0 for falsey, 1 for truthy, etc) stick with the unary +.