views:

3781

answers:

6

Try executing the following in JavaScript:

parseInt('01'); //equals 1
parseInt('02'); //equals 2
parseInt('03'); //equals 3
parseInt('04'); //equals 4
parseInt('05'); //equals 5
parseInt('06'); //equals 6
parseInt('07'); //equals 7
parseInt('08'); //equals 0 !!
parseInt('09'); //equals 0 !!

JavaScript, I just learned (the hard way), thinks that the leading zero indicates an octal integer, and since there is no "8" or "9" in base-8, the function returns zero. Like it or not, this is by design.

What are the workarounds?

Note: For sake of completeness, I'm about to post a solution, but it's a solution that I hate, so please post other/better answers.

+46  A: 

This is a common Javascript gotcha with a simple solution:

Just specify the base, or 'radix', like so:

parseInt('08',10); // 8

You could also use Number:

Number('08'); // 8
Paolo Bergantino
*Number*. Glorious.
Portman
Number needs quotes around the 08.Also just be warned, Number('08.123') will produce 8.123 as its output. If you really want an integer, don't use Number (or pattern-match your input to ensure integers only).
Jason S
Number(08); gives me 8 in Firefox and IE.
Paolo Bergantino
it's not part of the ECMAscript standard. I'm testing on JSDB which uses Spidermonkey 1.7 (=Firefox JS engine), and complains "08 is not a legal ECMA-262 octal constant"
Jason S
ah, I get a warning, not an error.
Jason S
Still, use '08' in quotes. 08 doesn't meet the ECMA-262 standard and isn't guaranteed to succeed w/o warnings and/or errors and/or a particular specified behavior.
Jason S
Fair enough, fixed.
Paolo Bergantino
+11  A: 

From the parseInt documentation, use the optional radix argument to specify base-10:

parseInt('08', 10); //equals 8
parseInt('09', 10); //equals 9

This strikes me as pedantic, confusing, and verbose (really, an extra argument in every single parseInt?) so I'm hoping there is a Better Way.

Portman
if you Don't Like Verbosity then just make your own function that calls the builtin function and fills in the arguments you always keep constant.
Jason S
Riiiiiiight, because it's not like every single person on StackOverflow would berate you for writing function parseIntB10.Writing your own wrapper function is a terrible idea for this purpose.
Stefan Kendall
@iftrue: I think you missed my point. I personally don't mind just doing parseInt(someString, 10) everywhere to ensure that I force base 10. The OP appears not to like this approach, so I suggested an alternative, which I wouldn't personally use but perhaps it meets his needs. (this is apparently the thinking behind JQuery: make it convenient by adding extra complexity. I don't use JQuery but many people find it useful.)
Jason S
+4  A: 

Specify the base:

var number = parseInt(s, 10);
RichieHindle
Wow you guys are fast. I even had my answer on the clipboard. Are you plugged directly into the Internet, Neo-style?
Portman
@Portman: There is no Internet.
RichieHindle
Why the devil is it not defaulted to base 10
Tom Gullen
+7  A: 
function parseDecimal(s) { return parseInt(s, 10); }

edit: making your own function, to do what you really want, is just an option if you don't like adding the ",10" all the time to the parseInt() call. It has the disadvantage of being a nonstandard function: more convenient for you if you use it a lot, but perhaps more confusing for others.

Jason S
+1 for putting it in a named function and hence making it self-documenting.
RichieHindle
+4  A: 

Would it be very naughty to replace parseInt with a version that assumes decimal if it has no second parameter? (note - not tested)

parseIntImpl = parseInt
parseInt = function(str, base){return parseIntImpl(str, base ? base : 10)}
Andrew Duffy
yes, that would be naughty -- it would break other code that relied on the standard behavior.
jes5199
That is true, but there isn't much of that. It also isn't standard behaviour - octal support is optional.
Andrew Duffy
+8  A: 

If you know your value will be in the signed 32 bit integer range, then ~~x will do the correct thing in all scenarios.

~~"08" === 8
~~"foobar" === 0
~~(1.99) === 1
~~(-1.99)  === -1

If you look up binary not (~), the spec requires a "ToInt32" conversion for the argument which does the obvious conversion to an Int32 and is specified to coerce NaN values to zero.

Yes, this is incredibly hackish but is so convenient...

Karl Guertin
+1 i didnt know this
NightCoder