287

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 !!

I just learned the hard way that JavaScript thinks 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.


Update:

The 5th Edition of the JavaScript standard (ECMA-262) introduces a breaking change that eliminates this behavior. Mozilla has a good write-up.

cнŝdk
32.2k7 gold badges62 silver badges81 bronze badges
asked May 11, 2009 at 22:14
10
  • 22
    Step 1) Do yourself a favor and always include the radix as mentioned in the previous answers as well as in Doug's book. Step 2) If you are serious about learning JavaScript, then get yourself a copy of Doug's book. It is invaluable. My fav book so far. Here's a review fyi: realtech.burningbird.net/learning-javascript/basics/… Commented May 12, 2009 at 1:25
  • 9
    In ECMAScript 5th Edition-compatible browsers, such as Internet Explorer 9, the base parameter defaults to 10 (decimal) unless the number to parse is prefixed with 0x, e.g. 0xFF, in which case the base parameter defaults to 16. Hopefully, one day, this issue will be a distant memory. Commented May 9, 2011 at 10:02
  • 2
    How about just +'08' === 8? True! Maybe you really need parseInt for your real code, but not for the above. Commented Dec 24, 2011 at 14:04
  • 1
    a) this is not a bug, fix the title b) Number('08') Commented Jan 6, 2012 at 20:01
  • 4
    @portman: "the 5th Edition...introduces a breaking change that eliminates this behavior" Probably worth pointing out that even in the 3rd edition (13 years ago), implementations were "encouraged" not to do it: "When radix is 0 or undefined and the string's number begins with a 0 digit not followed by an x or X, then the implementation may, at its discretion, interpret the number either as being octal or as being decimal. Implementations are encouraged to interpret numbers in this case as being decimal." (my emphasis) Commented Feb 8, 2012 at 10:04

10 Answers 10

333

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
groovecoder
1,5811 gold badge17 silver badges29 bronze badges
answered May 11, 2009 at 22:15
5
  • 11
    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). Commented May 11, 2009 at 22:22
  • 3
    Number(08); gives me 8 in Firefox and IE. Commented May 11, 2009 at 22:23
  • 3
    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" Commented May 11, 2009 at 22:25
  • 5
    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. Commented May 11, 2009 at 22:52
  • Old question, but note that Number is different than parseInt: stackoverflow.com/a/4090577 Commented Feb 3, 2017 at 22:51
45

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

answered Jan 5, 2010 at 14:15
4
  • 3
    Why two operations when one binary or would suffice? Commented Aug 7, 2012 at 17:55
  • @Oleg, Why would one suffice? Commented Mar 29, 2013 at 19:16
  • @Grodriguez, and when 0 in |0 is a string? Commented Oct 24, 2014 at 16:29
  • This whole question is about alternatives to parseInt for converting strings to integers. Thus: always. Commented Oct 25, 2014 at 9:55
24

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.

answered May 11, 2009 at 22:16
4
  • 7
    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. Commented May 11, 2009 at 22:20
  • 3
    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. Commented May 11, 2009 at 22:36
  • 2
    @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.) Commented May 11, 2009 at 23:26
  • 6
    Actually it's really important to wrap parseInt for convenient use in functional expressions, like map in ["7","4","09","5"].map(parseInt); Map will pass the index of the element in the array as the second argument, which will be interpreted by parseInt as the base unless you wrap it. Commented Feb 24, 2013 at 7:16
12
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.

answered May 11, 2009 at 22:19
0
10

Specify the base:

var number = parseInt(s, 10);
answered May 11, 2009 at 22:16
4
  • Wow you guys are fast. I even had my answer on the clipboard. Are you plugged directly into the Internet, Neo-style? Commented May 11, 2009 at 22:17
  • 1
    Why the devil is it not defaulted to base 10 Commented Aug 21, 2010 at 10:08
  • 2
    Maybe because it's not primarily meant as a String->Number converting function, but a function that reads a Number from a base b number String. Commented Nov 16, 2010 at 22:13
  • 3
    it is defaulted to base 10 but leading zeros are a widespread way to indicate octal. Commented Dec 8, 2010 at 22:09
7

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)}
answered May 12, 2009 at 0:44
4
  • 2
    yes, that would be naughty -- it would break other code that relied on the standard behavior. Commented Oct 3, 2009 at 22:53
  • 4
    That is true, but there isn't much of that. It also isn't standard behaviour - octal support is optional. Commented Oct 5, 2009 at 10:14
  • 3
    But you're also dropping hex support which isn't optional, is it? This should always be true: parseInt("0xFFFFFF") === 16777215, but with your naughty hack in place it no longer works parseInt("0xFFFFFF") === 0 Commented Nov 6, 2013 at 16:23
  • 2
    @jes5199 But then ECMAScript 5 decided to break other code that relied on that behavior Commented Jan 23, 2018 at 21:24
7

You may also, instead of using parseFloat or parseInt, use the unary operator (+).

+"01"
// => 1
+"02"
// => 2
+"03"
// => 3
+"04"
// => 4
+"05"
// => 5
+"06"
// => 6
+"07"
// => 7
+"08"
// => 8
+"09"
// => 9

and for good measure

+"09.09"
// => 9.09

MDN Link

The unary plus operator precedes its operand and evaluates to its operand but attempts to convert it into a number, if it isn't already. Although unary negation (-) also can convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number.

answered Jul 18, 2015 at 0:30
5

How about this for decimal:

('09'-0) === 9 // true
('009'-0) === 9 // true
Mark Hall
54.7k9 gold badges100 silver badges116 bronze badges
answered Jan 20, 2012 at 3:20
5

This issue cannot be replicated in (削除) latest* (削除ここまで) Chrome or Firefox (2019).

Test:

console.log(parseInt('08'));

*"Since (ECMAScript 5) JavaScript has abandoned this behaviour, but you should still specify the radix to satisfy older browsers." Source

Kostas Minaidis
5,6424 gold badges21 silver badges31 bronze badges
answered Oct 9, 2019 at 19:29
2
  • 2
    Yeah, looks like someone finally decided the octal stuff caused more problems than it solved. Though would hate to be one of the 0.01% of people who actually used/relied upon the feature where anything with a leading 0 would parse as octal. :) Commented Sep 2, 2020 at 5:26
  • 2
    That's going to cause some really nasty bugs for some people! Commented Sep 4, 2020 at 1:47
4

If you've done a bunch of coding already with parseInt and don't want to add ",10" to everything, you can just override the function to make base 10 the default:

window._oldParseInt = window.parseInt;
window.parseInt = function(str, rad) {
 if (! rad) {
 return _oldParseInt(str, 10);
 }
 return _oldParseInt(str, rad);
};

That may confuse a later reader, so making a parseInt10() function might be more self-explanatory. Personally I prefer using a simple function than having to add ",10" all the time - just creates more opportunity for mistakes.

answered Jul 17, 2011 at 6:05

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.