I hunted down a bothersome JavaScript error where I was passing one argument, but when it was received, it was something completely different. I fixed it, but would like to know what was happening for future reference.
What I should have passed as an argument is '0616' (with quotes). What I actually passed was 0616 (without the quotes).
So, when it was received, some kind of implicit numeric conversion took place, and it was received as 398. I understand implicit and explicit conversion, but WHAT was happening to turn 0616 into 398. The leading zero seems to have something to do with it because other values that I passed that were non-zero in the most significant digit survived just fine. It's only those that begin with zero?
But what relation is there between 398 and '0616' ?
Any ideas?
Ahh the magical world of javascript!!
Any numeric literal that starts with a 0 is treated as an octal number.
A hacky workaround is
parseInt('0616', 10)
0616 is the old octal number format. In new spec it should be 0o616, however the old format is still supported by browsers.
See this wiki page:
prefix 0o was introduced to .... and it is intended to be supported by ECMAScript 6 (the prefix 0 has been discouraged in ECMAScript 3 and dropped in ECMAScript 5).
the reason is that the leading zero is javascript notation for base octal, e.g. 010 = 8. The notation for hexadecimal is a leading 0x, e.g. 0x10 = 16
Related
I have a button where in the code behind I add a onclick and I pass a unique ID which will be passed to the js function. The id starts with a 0.
It wasn't working and eventually I figured out that the number, id, it was passing was wrong...
Ie. see this: js fiddle
It works with a ' at the start and end of the number. Just wondering why 013 turns to 11. I did some googling and couldn't find anything...
Cheers
Robin
Edit:
Thanks guys. Yep understand now.
As in this case the 0 at the start has a meaning, here the recipient ID in a mailing list, I will use '013' instead of just 013, i.e. a string. I can then split the values in js as each of the 3 values represents a different id which will always be only 1 character long, i.e. 0-9.
A numeric literal that starts with a 0 is treated as an octal number. So 13 from base 8 is 11 in base 10...
Octal numeric literals have been deprecated, but still work if you are not in strict mode.
(You didn't ask, but) A numeric literal that starts with 0x is treated as hexadecimal.
More info at MDN.
In your demo the parameter is called id, which implies you don't need to do numerical operations on it - if so, just put it in quotes and use it as a string.
If you need to be able to pass a leading zero but still have the number treated as base 10 to do numerical operations on it you can enclose it in quotes to pass it as a string and then convert the string to a number in a way that forces base 10, e.g.:
something('013');
function something(id){
alert(+id); // use unary plus operator to convert
// OR
alert(parseInt(id,10)); // use parseInt() to convert
}
Demo: http://jsfiddle.net/XYa6U/5/
013 is octal, not decimal, it's equal 11 in decimal
You should note that 013 starts with a 0. In Javascript, this causes the number to be considered octal. In general you'll want to use the decimal, and hexadecimal number systems. Occasionally though, octal numbers are useful, as this question shows.
I hope this helps! :)
If the first digit of a number is a zero, parseInt interprets the number as an octal.
You can specify a base of ten like this:
parseInt(numberString, 10)
You could also remove such zeros with a regex like this (the result will be a string):
numberString.replace(/^0+/g, '');
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Workarounds for JavaScript parseInt octal bug
I would think it has something to do with octal parsing, since it only happens on 8 or 9. There was also the thought that this was a Chrome bug, but it replicates in Firefox as well.
Is this intentional behavior? If so, why?
The solution here is simple. NEVER call parseInt() without specifying the desired radix. When you don't pass that second parameter, parseInt() tries to guess what the radix is based on the format of the number. When it guesses, it often gets it wrong.
Specify the radix like this and you will get the desired result:
parseInt("08", 10) == 8;
As to what rules it uses for guessing, you can refer to the MDN doc page for parseInt().
If radix is undefined or 0, JavaScript assumes the following:
If the input string begins with "0x" or "0X", radix is 16
(hexadecimal).
If the input string begins with "0", radix is eight
(octal). This feature is non-standard, and some implementations
deliberately do not support it (instead using the radix 10). For this
reason always specify a radix when using parseInt.
If the input string
begins with any other value, the radix is 10 (decimal). If the first
character cannot be converted to a number, parseInt returns NaN.
So, according to these rules, parseInt() will guess that "08" is octal, but then it encounters a digit that isn't allowed in octal so it returns 0.
When you pass a number to parseInt(), it has nothing to do because the value is already a number so it doesn't try to change it.
"Is this intentional behavior?"
Yes.
"If so, why?"
A leading 0 is the notation used for denoting an octal number as defined in the specification. The symbols 8 and 9 don't exist in octal numbering, so parseInt uses the first valid number it finds, which is 0.
If you do...
parseInt('123#xq$_.f(--_!2*')
...the result will be...
123
...because a valid number was found at the beginning of the string. Anything invalid beyond that is discarded.
You can fix this like that :
parseInt("080".replace(/^[0]+/g,""));
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Workarounds for JavaScript parseInt octal bug
Surprisingly it returns 0. Why? and what's the (proper) solution to get correct results?
Use a radix:
var x = parseInt("08", 10);
Some JavaScript implementations add a third numeral system to the two defined by the standard (decimal, the default; and hex, prefixed with 0x): Octal, prefixed with 0. This is non-standard but acknowledged as common in the latest spec.
Since 8 is not a valid octal digit, parseInt stops there, returning the value 0.
By explicitly using a radix, you tell parseInt not to try to figure out what numeral system is being used but instead to use the one you specify. Your instinct when typing parseInt should always be to specify the radix; not doing so leaves you open to oddities.
"08" mean 8 based number. You should specify second argument.
parseInt("08", 10)
#T.J. gave a great explanation for the behaviour you see. Another way to parse a number string is to use unary +:
var num = +"08";
From http://www.bennadel.com/blog/2012-Exploring-Javascript-s-parseInt-And-parseFloat-Functions.htm:
Strings that start with "0" are assumed to be base8 (octal).
From MDC - parseInt:
If the input string begins with "0", radix is eight (octal). This feature is non-standard, and some implementations deliberately do not support it (instead using the radix 10). For this reason always specify a radix when using parseInt.
And the example:
parseInt("08"); // 0, '8' is not an octal digit.
That is, since no radix was passed in and the string begins with 0 octal is assumed. Since 8 is not an octal digit it cannot be parsed.
Solution? Always provide a radix parameter:
parseInt("08", 10);
If you run it through jslint, it'll squawk at you for not including the radix parameter. Yes, the radix is optional, but probably should be included every time. A number starting with 0 is assumed to be octal unless otherwise specified.
var foo = parseInt("08", 10);
Number prefixed with "0" is octal number. 8 is invalid octal number. so the result is 0
In JavaScript it is valid to end an integer numeric literal with a dot, like so...
x = 5.;
What's the point of having this notation? Is there any reason to put the dot at the end, and if not, why is that notation allowed in the first place?
Update: Ok guys, since you mention floats and integers... We are talking about JavaScript here. There is only one number type in JavaScript which is IEEE-754.
5 and 5. have the same value, there is no difference between those two values.
I guess it is just compatibility with other C-like languages where the dot does matter.
You DO need the decimal point if you call a method on an integer:
5.toFixed(n) // throws an error
5..toFixed(n) // returns the string '5.' followed by n zeroes
If that doesn't look right, (5).toFixed(n), or 5.0.toFixed(n), will work, too.
That's a floating point number. Unlike any other language I've ever encountered, all numbers in Javascript are actually 64-bit floating numbers. Technically, there are no native integers in Javascript. See The Complete Javascript Number Reference for the full ugly story.
The correct answer in this case is, that it makes absolutely no difference.
Every number in JavaScript is already a 64bit floating point number.
The ". syntax" is only useful in cases where you can ommit the fixed part because it's 0:
.2 // Will end up as 0.2
-.5 // Will end up as -0.5
So overall it's just saving a byte, but it makes the code less readable at the same time.
What if it wouldn't be an integer, but a floating point literal?
From what I understand, octal literals (of the form 023) are not valid in ECMAScript 5, but are widely supported. In ECMAScript 6, they are newly supported in the format 0o23 or 0O23. What confuses me is the behavior of numbers that are not valid octal numbers, but have a preceding zero (019). These seem to behave as normal, decimal numbers.
So without strict mode, I can get things like 022 === 018 (true), because 022 is interpreted as octal, and presumably 018 is treated as decimal since it can't be octal.
In strict mode, I get an error when using a valid octal number in that format (eg 022), but not when using a zero-prefixed number that can't be a valid octal number (eg 018).
This seems very odd to me, like JS (strict-mode) is telling me that I can put a 0 in front of my number, as long as it is an INVALID octal. In ES6 (or later), will zero-prefixed numbers (possible octals or otherwise) be invalid, or treated as decimals?
This is a documented feature:
Decimal literals can start with a zero (0) followed by another
decimal digit, but If all digits after the leading 0 are smaller than
8, the number is interpreted as an octal number. This won't throw in
JavaScript.
If you want to force treating a number as octal you can use new literal form 0o (or 0O) introduced in ES6.