Brady Dowling
Brady Dowling

Reputation: 5532

What's the difference between lodash toNumber and parseInt?

I know Lodash often adds some extra checks or niceties to functions that already exist in JavaScript but it's not clear what _.toNumber specifically does that I wouldn't get with parseInt.

I'd prefer to use Lodash only when it provides benefits that aren't there with existing JavaScript functions but I can't see any in this case.

Upvotes: 4

Views: 14225

Answers (2)

Akrion
Akrion

Reputation: 18525

I think it is much better to simply look at the _.toNumber source and that would practically answer your question:

function toNumber(value) {
  if (typeof value == 'number') {
    return value;
  }
  if (isSymbol(value)) {
    return NAN;
  }
  if (isObject(value)) {
    var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
    value = isObject(other) ? (other + '') : other;
  }
  if (typeof value != 'string') {
    return value === 0 ? value : +value;
  }
  value = value.replace(reTrim, '');
  var isBinary = reIsBinary.test(value);
  return (isBinary || reIsOctal.test(value))
    ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
    : (reIsBadHex.test(value) ? NAN : +value);
}

As you can see it does a bunch of other things in comparison to parseInt. To be more specific:

console.log(_.toNumber(1),       parseInt(1))        // same 
console.log(_.toNumber('1'),     parseInt('1'))      // same  
console.log(_.toNumber('b'),     parseInt('b'))      // same  
console.log(_.toNumber({}),      parseInt({}))       // same 
console.log(_.toNumber(' 1 '),   parseInt(' 1 '))    // same
console.log(_.toNumber([1]),     parseInt([1]))      // same
console.log(_.toNumber(' 1a1 '), parseInt(' 1a1 '))  // NaN      1
console.log(_.toNumber([1,2]),   parseInt([1,2]))    // NaN      1
console.log(_.toNumber(false),   parseInt(false))    // 0        NaN
console.log(_.toNumber(!0),      parseInt(!0))       // 1        NaN
console.log(_.toNumber(!!0),     parseInt(!!0))      // 0        NaN
console.log(_.toNumber(5e-324),  parseInt(5e-324))   // 5e-324   5
console.log(_.toNumber(5.5),     parseInt(5.5))      // 5.5      5
console.log(_.toNumber(null),    parseInt(null))     // 0        NaN
console.log(_.toNumber(Infinity),parseInt(Infinity)) // Infinity NaN
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

So to summarize _.isNumber gives you more expected / consistent and I would argue safer results when it comes to parsing input with arrays, decimals, falsy values and strings. It would check the entire input vs parseInt which only cares about the first valid value as you can see from the examples above. It also handles better the negate operator (!) etc.

So overall it does have its uses vs parseInt

Note: What is a gotcha here is that both _.toNumber and parseInt return NaN for undefined which considering how _.toNumber deals with the rest of the falsy values one would expect to return 0 vs NaN:

console.log(_.toNumber(undefined), parseInt(undefined))  // NaN NaN

Upvotes: 19

d_shiv
d_shiv

Reputation: 1790

_.toNumber converts a given input to a number if such a conversion is possible, otherwise returns NaN. The parseInt and parseFloat methods also work in same manner (the former will only return integers though), however, they are much more lax in their parsing rules. _.toNumber is significantly more restrictive.

For eg, with same input '5.2a', parseInt would return 5, parseFloat would return 5.2, and _.toNumber would return NaN. The former two ignore everything after the first unrecognised character and return the number formed by all parsed characters till that point. The last one however returns NaN if an unrecognised character is encountered.

_.toNumber is comparable and functionally same to Number function.

Upvotes: 3

Related Questions