This is something I see all the times, you have some code where at some point you have a variable that contains a number, maybe it comes from a for...
For further actions, you may consider blocking this person and/or reporting abuse
Unless you're doing this in the order of hundreds of thousands, performance is neglible (I've rarely come across use cases like this in prod systems)
While it's nice to think about these things and how you write code, I will always push back on people looking to enforce issues or 'standards' like this in PRs because they're rather subjective POV on style or rely on contrived performance benefits. If this seems like a harsh response, I apologise, but I'm wary of articles with titles like you 'should' be doing this, or you 'must not' do this, etc.
This is so true. Instead of pushing back just add a math.round to the Number() and the readability suffers and probably the performance too. I agree, the suggested „optimization“ is not worth implementing and worth thinking about in most real world use cases.
Two things here -
parseInt
doesn't do any rounding, only truncation. The equivalentMath
function would beMath.trunc
:Running benchmarks in Chrome, the performance benefit of
parseInt
overMath.round
is reversed if you explicitly convert to a number first:Kudos!
Good to know, thanks!
Today is finally the day I could use the information from this article. I came across a case where I had to cast a string to number. Worked flawlessly and
Number()
provides a nice interface to work with 👍Ok, but you did sum up the issue yourself in the examples. ParseInt will order to an integer whereas Number will get the proper numeric representation. Which means the outcome ma not be an int, which is what ParseInt guarantees .
The use of ParseInt can be replaced with Number if and only if it's accompanied by Math.round. This is not an edge case or an odd use case, it's the missing piece to have the intended outcome: an integer. The odd case is requiring the use of radix.
True, in fact if you want to take a string that could contain a float, and you want an integer, in that case you want to use that, but I'm not talking about that case, I'm talking about having the actual number correctly translated from a string to a number, which is probably the most common case.
My point is mostly:
The most common case for ParseInt is to get the correct number from a string with the even expectation of getting a float .... from a function that has int in the name? I hardly believe that.
I have never seen in 20 years a case of parseInt used with the expectation of getting anything except an int.
Unfortunately I see it using it for what Number is supposed to do, many, many times.
Btw, if you just need to get the integer (that is a positive number) from a string containing a float, then you should use double tilde operator, which does the same as
Math.floor
, but just 10 times faster (in Node at least), for example:double tilde...🤯
Shorter.
By the way, you will need
parseInt
anyway, if you want to deal with custom base number other than10
. Example is to convert HEX color code into RGB color code:Very useful and well written post! Thank you!
What about
eval()
?It will be an overkill. There are so many working ways of parsing integers. Why bother using such a dangerous way?
eval is dangerous..
eval("alert('you are hacked')")
I get your point, but you can already run JS commands in the console. Also, you can use
str.includes("()")
.However, end users being able to use console to execute any code doesn't necessarily mean that they will want to do it proactively. If you use
eval
and if the input is harmful, the end user may be passively affected.Potentially, but can't you check the string for functions using 'str.includes("()")'?
If you are referring to checking if the string contains function call by searching for
"()"
, no it won't work because there are way too many scenarios. Consider a case when there are spaces in between the parenthesis, e.g.foo( )
and your code will then allow it to run. It will be better if you only allow whitelisted characters. However, it will still take unnecessary effort and still potentially cause the program to hang (if you are going to search/parse the whole string which can be very long). So just use the built-in functions that work just fine and don't reinvent the wheel, which is something stupid.Don't do it.
eval() should never be used on user input.
Often parsing strings to Int is done for security reasons. Using eval() would just lead you to code injection and XSS problems.
Don't do it!
Keep in mind that both return different results when when passing nullish or boolean values:
This post is already a bit old, but the topic is still relevant. And the advice in this post is very much incomplete. Watch this:
The Number constructor is highly unreliable when it comes to interpreting user input from a form.
Unfortunately all oneliners in Javascript are broken. Nothing works. Neither
parseInt
norNumber
nor any other implicit or explicit attempt to convert the value.You always have to use a combination of different functions plus some manual checking for special cases like empty string, null, or undefined... otherwise you will always experience inconsistent behavior.
Or use +
But thanks for pointing it out, I've updated the article adding the test results using the unary operator and
parseFloat
with the unary operator is still 5/6 times slower than
Number
Interesting - I tested on Firefox and using the unary
+
was almost twice as fast asNumber
- jsbench.me/v2kurpao3r/1The same bench on Chrome showed the two methods almost exactly the same speed - sometimes one would be faster than the other, sometimes not
This is interesting, I run the tests using Node (v14.17.6), in "theory" it should give you similar results to Chrome as they both use V8 as the engine, but it's clearly different
This is cool, thanks for sharing.
Btw. for measuring the performance use
performance.now()
instead ofDate
, it's more precise.Thanks, forgot about that one!
I can't confirm this with my smartphone now with Android, Qualcomm's Snapdragon 665 and
schedutil
governor.parseInt('3.2')
andparseInt('3.2', 10)
andMath.trunc(Number('3.2'))
are consistently within 0,5% of each other in terms of time with stable Firefox 121.0 (20231214155439).Only
Math.trunc('3.2')
is always slower by 90%-98% with Chromium 120.0.6099.144 (Official Build) (64-bit), 122.0.6215.0 (Official Build) canary (64-bit) and Firefox 121.0 (20231214155439), 123.0a1 (20231230094435).I also noticed that
Math.trunc(Number('3.2'))
is 3%-5% slower with Chromium 122.0.6215.0 (Official Build) canary (64-bit). I don't know why.Use this or something better jsbench.me/bflqt42rdh/1
Valid, and in the case of any kind of game development this could have a massive impact on the performance of said game.
FYI,
Math.round()
will round the number, not chop off the decimal. Usefloor
or better yet|0
to drop the decimalAre you saying it will return an http code of 500?
ehm, no? :D
Strange, it looked like something had gone horribly wrong if you got 500 out of 1506.
I can at least see how an algorithm can utilize 5, but 500 is mind-boggling wrong.
One thing to note that caugth me by surprise is that
Number
will parse any falsy value as0
, soundefined
,null
,false
all parse fine and return0
, can be unexpected.Why not compare to parseFloat?
Anyway, parseInt forgivingness is so bad.
parseFloat is even worst than parseInt if you just want to convert a string to a number
Cool, i didnt knew about it!
Just small update instead of Number(something)
you can write +something and it will convert it to number
I know, it's on the article as well, it's called unary operator ;-)
You can also use this :
~~'234';
or even :
'234' | 0;
If the title/content of the article were about warning against using parseInt in canvas art or game development then that's a different conversation.
Why not save some time and use the simple '+' before the string you want to parse? Same result as Number, but quite faster to write
Thanks a lot! this helped me fix a bug I couldn't figure out where it came from