Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why JavaScript treats a number as octal if it has a leading zero

Tags:

javascript

var x = 010;
console.log(x); //8

JS engine convert the number x to octal number. Why it happens? How can I prevent it?

like image 348
Jagajit Prusty Avatar asked May 03 '16 12:05

Jagajit Prusty


People also ask

What is octal number in JS?

Octal numbersIf the digits after the 0 are outside the range 0 through 7, the number will be interpreted as a decimal number. Strict mode forbids this octal syntax.

What is the purpose of octal code?

Using octal is a convenient way to abbreviate binary numbers. Starting from the right, group all binary digits into sets of three. If the last group on the left does not have three digits, then add a zero. Each three-digit binary group translates into a one-digit octal number.

What is an octal literal?

An octal integer literal begins with the digit 0 and contains any of the digits 0 through 7.


2 Answers

I think my answer here answers the question, but the question is not exactly a duplicate, so I include a copy of my answer.

History

The problem is that decimal integer literals can't have leading zeros:

DecimalIntegerLiteral ::
    0
    NonZeroDigit DecimalDigits(opt)

However, ECMAScript 3 allowed (as an optional extension) to parse literals with leading zeros in base 8:

OctalIntegerLiteral ::
    0 OctalDigit
    OctalIntegerLiteral OctalDigit

But ECMAScript 5 forbade doing that in strict-mode:

A conforming implementation, when processing strict mode code (see 10.1.1), must not extend the syntax of NumericLiteral to include OctalIntegerLiteral as described in B.1.1.

ECMAScript 6 introduces BinaryIntegerLiteral and OctalIntegerLiteral, so now we have more coherent literals:

  • BinaryIntegerLiteral, prefixed with 0b or 0B.
  • OctalIntegerLiteral, prefixed with 0o or 0O.
  • HexIntegerLiteral, prefixed with 0x or 0X.

The old OctalIntegerLiteral extension has been renamed to LegacyOctalIntegerLiteral, which is still allowed in non-strict mode.

Conclusion

Therefore, if you want to parse a number in base 8, use the 0o or 0O prefixes (not supported by old browsers), or use parseInt.

And if you want to be sure your numbers will be parsed in base 10, remove leading zeros, or use parseInt.

Examples

  • 010
    • In strict mode (requires ECMAScript 5), it throws.
    • In non strict mode, it may throw or return 8 (implementation dependent).
  • 0o10, 0O10
    • Before ECMAScript 6, they throw.
    • In ECMAScript 6, they return 8.
  • parseInt('010', 8)
    • It returns 8.
  • parseInt('010', 10)
    • It returns 10.
like image 132
Oriol Avatar answered Sep 24 '22 03:09

Oriol


It's because some JavaScript engines interpret leading zeros as octal number literals. It is defined in an appendix of ECMAScript specification.

However, in strict mode, the conforming implementations must not implement that - see ECMAScript specification again:

A conforming implementation, when processing strict mode code (see 10.1.1), must not extend the syntax of NumericLiteral to include OctalIntegerLiteral as described in B.1.1.

Because of this ambiguity, it's better not to use leading zeros.

like image 28
Ondra Žižka Avatar answered Sep 24 '22 03:09

Ondra Žižka