Although unary negation ( - ) also can convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number.
Hence for converting some non-numeric value to number we should always use Number() function. eg. There are various corner case to parseInt() functions as it does redix conversion, hence we should avoid using parseInt() function for coersion purposes.
The parseInt() function is used to accept the string ,radix parameter and convert it into an integer. The radix parameter is used to specify which numeral system to be used, for example, a radix of 16 (hexadecimal) indicates that the number in the string should be parsed from a hexadecimal number to a decimal number.
parseInt() doesn't always correctly convert to integer In JavaScript, all numbers are floating point. Integers are floating point numbers without a fraction. Converting a number n to an integer means finding the integer that is “closest” to n (where “closest” is a matter of definition).
The ultimate whatever-to-number conversion table:
EXPRS = [
'parseInt(x)',
'parseFloat(x)',
'Number(x)',
'+x',
'~~x',
'x>>>0',
'isNaN(x)'
];
VALUES = [
'"123"',
'"+123"',
'"-123"',
'"123.45"',
'"-123.45"',
'"12e5"',
'"12e-5"',
'"0123"',
'"0000123"',
'"0b111"',
'"0o10"',
'"0xBABE"',
'"4294967295"',
'"123456789012345678"',
'"12e999"',
'""',
'"123foo"',
'"123.45foo"',
'" 123 "',
'"foo"',
'"12e"',
'"0b567"',
'"0o999"',
'"0xFUZZ"',
'"+0"',
'"-0"',
'"Infinity"',
'"+Infinity"',
'"-Infinity"',
'null',
'undefined',
'true',
'false',
'Infinity',
'NaN',
'{}',
'{valueOf: function(){return 42}}',
'{toString: function(){return "56"}}',
];
//////
function wrap(tag, s) {
if (s && s.join)
s = s.join('');
return '<' + tag + '>' + String(s) + '</' + tag + '>';
}
function table(head, rows) {
return wrap('table', [
wrap('thead', tr(head)),
wrap('tbody', rows.map(tr))
]);
}
function tr(row) {
return wrap('tr', row.map(function (s) {
return wrap('td', s)
}));
}
function val(n) {
return n === true || Number.isNaN(n) ? wrap('b', n) : String(n);
}
var rows = VALUES.map(function (v) {
var x = eval('(' + v + ')');
return [v].concat(EXPRS.map(function (e) {
return val(eval(e))
}));
});
document.body.innerHTML = table(["x"].concat(EXPRS), rows);
table { border-collapse: collapse }
tr:nth-child(odd) { background: #fafafa }
td { border: 1px solid #e0e0e0; padding: 5px; font: 12px monospace }
td:not(:first-child) { text-align: right }
thead td { background: #3663AE; color: white }
b { color: red }
Well, here are a few differences I know of:
An empty string ""
evaluates to a 0
, while parseInt
evaluates it to NaN
. IMO, a blank string should be a NaN
.
+'' === 0; //true
isNaN(parseInt('',10)); //true
The unary +
acts more like parseFloat
since it also accepts decimals.
parseInt
on the other hand stops parsing when it sees a non-numerical character, like the period that is intended to be a decimal point .
.
+'2.3' === 2.3; //true
parseInt('2.3',10) === 2; //true
parseInt
and parseFloat
parses and builds the string left to right. If they see an invalid character, it returns what has been parsed (if any) as a number, and NaN
if none was parsed as a number.
The unary +
on the other hand will return NaN
if the entire string is non-convertible to a number.
parseInt('2a',10) === 2; //true
parseFloat('2a') === 2; //true
isNaN(+'2a'); //true
As seen in the comment of @Alex K., parseInt
and parseFloat
will parse by character. This means hex and exponent notations will fail since the x
and e
are treated as non-numerical components (at least on base10).
The unary +
will convert them properly though.
parseInt('2e3',10) === 2; //true. This is supposed to be 2000
+'2e3' === 2000; //true. This one's correct.
parseInt("0xf", 10) === 0; //true. This is supposed to be 15
+'0xf' === 15; //true. This one's correct.
The table in thg435's answer I believe is comprehensive, however we can summarize with the following patterns:
true
to 1, but "true"
to NaN
.parseInt
is more liberal for strings that are not pure digits. parseInt('123abc') === 123
, whereas +
reports NaN
.Number
will accept valid decimal numbers, whereas parseInt
merely drops everything past the decimal. Thus parseInt
mimics C behavior, but is perhaps not ideal for evaluating user input.parseInt
, being a badly designed parser, accepts octal and hexadecimal input. Unary plus only takes hexademical.Falsy values convert to Number
following what would make sense in C: null
and false
are both zero. ""
going to 0 doesn't quite follow this convention but makes enough sense to me.
Therefore I think if you are validating user input, unary plus has correct behavior for everything except it accepts decimals (but in my real life cases I'm more interested in catching email input instead of userId, value omitted entirely, etc.), whereas parseInt is too liberal.
I recommend use Math.floor (or ~~ if you know numbers are positive) instead of parseString. +(expression) is out of scope, because +(expression) is more like parseFloat. Look this little benchmark:
// 1000000 iterations each one
node test_speed
Testing ~~, time: 5 ms
Testing parseInt with number, time: 25 ms
Testing parseInt with string, time: 386 ms
Testing Math.floor, time: 18 ms
The source code of benchmark:
/* el propósito de este script es evaluar
que expresiones se ejecutan más rápido para así
decidir cuál usar */
main()
async function main(){
let time, x
let number = 23456.23457
let test1 = ()=>{
x = 0
time = Date.now()
for(let i=0;i<1000000;i++){
let op = Math.floor(number / 3600)
x = op
}
console.info("Testing Math.floor, time:", Date.now() - time, "ms")
}
let test2 = ()=>{
x = 0
time = Date.now()
for(let i=0;i<1000000;i++){
let op = parseInt(number / 3600)
x = op
}
console.info("Testing parseInt with number, time:", Date.now() - time, "ms")
}
let test3 = ()=>{
x = 0
time = Date.now()
for(let i=0;i<1000000;i++){
let op = parseInt((number / 3600).toString())
x = op
}
console.info("Testing parseInt with string, time:", Date.now() - time, "ms")
}
let test4 = ()=>{
x = 0
time = Date.now()
for(let i=0;i<1000000;i++){
let op = ~~(number / 3600)
x = op
}
console.info("Testing ~~, time:", Date.now() - time, "ms")
}
test4()
test2()
test3()
test1()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With