4

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.

Brady Dowling
  • 4,920
  • 3
  • 32
  • 62

2 Answers2

19

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
Akrion
  • 18,117
  • 1
  • 34
  • 54
  • 1
    Good point, I should have just checked the source to begin with. I'll do this for future lodash questions like this because I always think this way. – Brady Dowling Jun 12 '19 at 13:47
  • I would like to suggest correction to the above answer. I think it might be misleading by saying that lodash toNumber gives more expected results. Please extend your examples with following values: 10% 100$ $100 or any other currency character. Both parseInt and parseFloat handles them as one would expect, where toNumber returns NaN. – Nevararn Dec 07 '20 at 11:46
3

_.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.

d_shiv
  • 1,670
  • 10
  • 8