Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript JavaScript Numbers Working with Numbers Convert Strings to Numbers

Ryan M
Ryan M
16,509 Points

Any reason why Number() was not mentioned? Seems to function almost exactly the same as unary plus + operator

Number() seems to return almost exactly the same values as the unary plus + operator but it wasn't mentioned. Is there any reason why? It's definitely more readable even though it's longer.

3 Answers

Oh, really interesting question, Ryan! I think the most straightforward answer to your question is that - at least in this stage of your expected / assumed learning process - the unary plus (+) operator can be explained in terms that are more meaningful or digestible than delving into the Number() constructor. To really get a grasp of how the Number() constructor works, or to explain it in an effective way, you'd need to familiarise yourself with objects (and primitive wrapper objects), and constructors. But it's not really needed at this point.

You're totally right that the Unary (+) Operator will return the same values at Number(), and that's because it's completing the same process under the hood.

This is taken from the ECMA specs for the Unary (+) Operator:

11.4.6 Unary + Operator The unary + operator converts its operand to Number type.

Basically, it's the equivalent to the Number() constructor called as a function. It achieves the same goal, but is a little easier to write and understand - and helps achieve the goal of making coding more accessible.

Ryan M
Ryan M
16,509 Points

Thank you Chris :) This helps a lot!

Steven Parker
Steven Parker
230,946 Points

Actually, parseInt() is preferred for most situations. The behaviors of the various conversion mechanisms varies a bit, it's a good idea to understand how they differ before making a choice. Here's a chart of examples for each:

chart

Ryan M
Ryan M
16,509 Points

Thank you Steven :) is there a reason why parseInt() is preferred? I came across this table online and it does help. I then experimented with various values myself and it looks like Number() and unary + now return NaN for booleans and null the same way parseInt() and parseFloat() do.

Steven Parker
Steven Parker
230,946 Points

One thing I've personally found handy about parseInt() is that if you give it something like "32px" it will return 32, where Number() or unary + will return NaN. On the other hand, an empty string will return NaN from parseInt(), but Number()/+ will oddly return 0.

This is a really interesting discussion! I might run a few tests a bit later today, but I think the comments Steven Parker outlined about the behaviour of parseInt() vs Number() / unary (-/+) operators is pretty consistent with the outlined spec.

For your benefit, Ryan McFarlane, we can dig a little deeper and look under the hood. It can get a little complex as we poke further down the hole, so don't worry about some of the terminology right now - it's not too important right now.

So, Number is a primitive wrapper object - it's a standard built in object used to represent and manipulate numbers. When we use the Number() constructor or unary (+) operator, we're attempting to create a new Number object. But it doesn't just say "okay, this is now a number" - it runs its own processes to evaluate the validity of what you've entered.

According to the ECMA specs for the Number Constructor, when Number is called with an argument (so there's a value present between the parentheses), a few steps are taken. An abstract operation called ToNumeric(value) is performed, which converts the value into a primitive in the form of a Number or a BigInt, type checks it to confirm that it is in fact either a Number or BigInt, and returns a response. White space is trimmed (so you could enter Number(" 5 " ) and still return 5. However, if you were to pass a pixel value as an argument (for example Number("32px") ) you'd throw an error, as 32px is neither a Number nor a BigInt. Test is failed.

Interestingly, where Steven noted passing Number() an empty string returns 0, this comes down to the nature of Boolean objects in JavaScript. The MDN Docs for Boolean objects notes that an empty string has an initial boolean value of false. Number() then runs its operation as Number(false), calls ToNumeric(value) when then in turn returns the ToNumber(argument) abstract operation...which returns 1 if the argument is true, and returns 0 if the argument is false.

So - the long and short of it is that if you were to pass a string such as "tomato" to the Number() constructor, it would be interpreted as a string and the conversion would fail. You'll get NaN returned. But if you were to pass it an empty string, it would be interpreted as false per the Boolean object standards, which then gets evaluated and returned as a 0. What a whirlwind.

parseInt(), on the other hand, is a method on the Number object. It performs a similar process to the Number() constructor, but it contains a number of additional steps to convert and trim a string. So instead of just trimming whitespace and attempting a raw interpretation and conversion of the value, it has defined steps within the method to extract the longest valid numerical range within the string. If you take a look at the ECMA specs you'll see a range of additional steps - in fact, parseFloat() ultimately will call ToString(), TrimString(), ParseText(), StringToCodePoint() among other additional abstract functions. The result is that in my string " 25421px " only the series of digits are extracted and type converted using the Number() constructor.

Phew. That was interesting. Now time for a coffee.

Commenting to come back and explore this interesting rabbit hole. Thanks everyone!