Some notes about conversion to number in javascript
javascript has lots of methods to convert any value to number
- all methods could be divided into 2 groups: string and native methods
- String methods are parseInt and parseFloat
- Native mathods are Number and Math methods
all native methods behave the same way, sometimes with additional transform
for converting to Number best choices are parseFloat and Number to convert to integer you can use parseInt and Math.round
Number("13.2") //13.2
parseFloat("13.2") //13.2
parseInt("13.2") // 13
Math.round("13.2") // 13
they both work well for valid number strings but have different behavior on some values
- trailing garbage
// string funcions read valid part and ignore trailing garbage
parseFloat("14.5px") // 14.5
parseInt("14.5px") // 14
// native methods treat this values as invalid
Number("14.5px") // NaN
Math.round("14.5px") // NaN
- integer round
// parseInt just ignores trailing chars so it round number to near to zero
parseInt("12.7") // 12
// but Math has 3(4 in ES6) functions with different behavior
Math.round("12.7") // 13
Math.round("12.3") // 12
Math.floor("12.9") // 12
Math.ceil("12.1") // 13
- empty string
parseFloat("") // NaN
parseInt("") // NaN
Number("") // 0
Math.round("") // 0
- native javascript values
// but native functions have better support for nonstring values
[null, false, true].map(parseFloat) // [NaN, NaN, NaN]
[null, false, true].map(Number) // [0, 0, 1]
for Date parseInt and parseFloat return NaN, but Number return milliseconds from 1970-01-01 UTC(unixtime multiplied by 1000)
parseInt also can be also used for converting from nonstandard bases(from 2 to 36)
parseInt("file", 25) //246164
(246164).toString(25) // "file"
- parseInt and Number also support hex literal, but parseFloat doesn't
parseFloat("0xff") // 0
parseInt("0xff") // 255
Number("0xff") // 255
- objects
// if object has both toString and valueOf methods, string functions will use toString, native will use valueOf
var testObject = {
toString: function(){return "13"},
valueOf: function(){return "42"}
};
parseFloat(testObject) // 13
parseInt(testObject) // 13
Number(testObject) // 42
+testObject // 42
Math.round(testObject) // 42
testObject * testObject // 1764
testObject + testObject // "4242"
- operators
+"42" // 42
"42" - 0
"42" * 1
"42" / 1
// but `+` means string concat
"42" + 0 // "420"
// `-= 0`, `*=1`, `/=1`, ES6:`**1` can be also used to prevent writing variable's name twice
very.long.path.to.veryLongName.subObject.param -= 0;
- 32-bit integer conversion
// sometimes 32-bit conversion to integer is used
value|0
~~value
// invalid values are converted to 0
Number("a string") // NaN
"a string"|0 // 0
// but it truncates all higher bits in big numbers
1e10 | 0 // 1410065408
// look at both number in hex
(1e10).toString(16) // "2540be400"
(1410065408).toString(16) // "540be400"
(0xa9876543210 | 0) === (0x76543210) // true
in ES6 there's also Math.fround function to convert to float32
Math.fround("1.3") // 1.2999999523162842
extra + fun + dumb functions
// convert to n-bit unsigned integer for any n from 1 to 31:
value & ((1<<n)-1)
// just for fun
value % Infinity // but Infinity % Infinity is NaN
Math.pow(value, 1)
// in ES6 there's also
value ** 1;
// sometimes eval and JSON.parse work too
eval("42") // 42
JSON.parse("42") //42
// but eval is unsafe
eval("location.href='http://spam.site'")
// JSON.parse can return other types
JSON.parse('{"key":"value"}') // Object {key: "value"}
// or throw an error
{
JSON.parse("invalid");
// the code below will not be called
}
/**
* you can also convert to other number types through typed arrays
* @param value - any value
* @param arrayClass - typedArray class
*/
function toTyped(value, arrayClass){
var array = new arrayClass(1);
array[0] = value;
return array[0];
}
toTyped("1234", Int8Array) // -46
toTyped("1234", Uint8Array) // 210
toTyped("1234", Uint8ClampedArray) // 255
toTyped("1.3", Float32Array) // 1.2999999523162842
toTyped("1.3", Float32Array) === "1.3" //false
toTyped("1.3", Float32Array) === Math.fround("1.3") //true