That's because "09" is an invalid number, in octal.
The parseInt() funciton acutally has 2 arguments that most people are not aware of, first is the string to parse and then a radix (which is optional). The radix value allows you to convert a binary (base 2), hexadecimal (base 16) or other base string to a decimal integer.
Example: parseInt("FF", 16); returns 255
The problem is that if you leave the radix argument off the function doesn't necessarily assume you want a decimal (base 10) conversion. Instead it checks the input string (the first argument) and if it starts with "0x" it assumes it's a hexadecimal value. If it starts with "0" - not followed by an "x" - it takes it as an octal value. This follows the JavaScript convention for numeric constants.
If you code
var x = 0x18;
alert(x);it will display 24 which is the decimal equivalent of the hex number "18". Likewise,
var x = 014;
alert(x);displays 12 which is the decimal value of the octal number "14".
Resource: FAQTs
Hexadecimal uses the numbers 0 to 9 and the letters A to F, 16 in all. You would normally see hexadecimal values used for colors (Orange: #FF9C00, White: #FFFFFF, or Red: #FF0000). Octal is base 8, so only the numbers 0-7 are valid. Hence, "09" is not a valid octal number and the function returns 0. Just as it would for "abc" in decimal ... it's not a valid number.
To avoid this, get into the habit of always adding the second argument, in this case ...
parseInt("09", 10);
returns 9 (decimal), as desired.
Resources
* FAQTs