I notice that strict equal operator returns true if the operands are equal and of the same type.
But, if I do this
01000 == 512; // returns true
01000 === 512; // returns true
or
0o535 == 349; // returns true
0o535 === 349; // returns true
Do they have the same value and type?
Because 01000, 512, 0o535, and 349 are all numbers. 01000 and 512 are the same value written different ways (a "legacy" octal literal and a decimal literal); so are 0o535 and 349 (a new-style octal literal and a decimal literal). The form of literal you use makes no difference to the value or type of what it creates. Similarly, 'foo' === "foo" is true, even though I use the single-quoted string literal in one and the double-quoted string literal in the other.
About the two kinds of octal literals:
01000 is a "legacy" octal literal, indicated by just the leading zero. JavaScript engines in web browsers are required (as of ES2015) to support them in loose mode, and to not support them in strict mode (e.g., "use strict"). (Note that loose mode and strict mode have nothing to do with loose equality and strict equality, which is a separate concept.) So in a compliant, browser-based JavaScript engine, 01000 === 512 is true in loose mode, but an error in strict mode, because legacy octal literals are not allowed in strict mode. (Prior to ES2015, supporting legacy octal literals in loose mode was not required.)
0o535 is the newer octal notation added in ES2015, indicated with the leading 0o. It's supported in both loose and strict modes by compliant JavaScript engines. But again, it's new, so older browsers won't be compliant.
If a number starts with 0, it is interpreted as octal, or base 8.
01000 in base 8 is 512 in base 10.
So they are equating to true. Because the value is anyway same.
Those are different ways of representing numbers and they're all of type "number". As an example
typeof 01000; //=> "number"
var num = 0o535;
num; //=> 349
Because they are equal and of the same type. They both are numbers. Number does not have anything like base - it's just a representation.
This is an interesting question because one may assume that === should be able to distinguish between different notations. However, this is not the case because JavaScript automatically interprets integers of different notations.
There are various numeric literals available. New notations for binary, octal, and hexadecimal are coming in from ES6.
1) decimal numbers are usually seen without a leading 0, but they can be written with one. If the next digit after the leading 0 is 8 or greater,
it is parsed as a decimal. Otherwise, it is parsed as an octal.
0800 === 800 --> decimal
0700 === 448 --> octal
0700 === 0o0700
Now for the new ES6 number features:
2) binary numbers have a leading 0b or 0B.
3) octal numbers have a leading 0o or 0O.
4) hexadecimal numbers have a leading 0x or 0X.
acturally, they have the same type :
typeof(01000) //"number"
typeof(0o535) //"number"
they are base 8 thought by js
The numbers you wrote (01000 and 0o535) are just octal representations of the numbers 512 and 349.
01000 = 0*8^0 +0*8^1 + 0*8^2 + 1*8^3 = 512
0o535 = 5*8^0 + 3*8^1 +5*8^2 = 5 + 24 + 320 = 349
javascript doesn't really care about the base you use to write your numbers.
Related
var x = 010;
console.log(x); //8
JS engine convert the number x to octal number. Why it happens? How can I prevent it?
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.
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.
JS treat numbers with leading zeros as octal only if they valid octal, if not then it treat it as decimal. To prevent this not use leading zeros in your source code
console.log(010, 10, +"010")
if (021 < 019) console.log('Paradox');
or use strict mode to not allow using leading zeros
'use strict'
if (021 < 019) console.log('Paradox');
I have a array like this.
var elements=[5614,6619,7220,7320,7830,8220,0111,0112,0113,0142,0149]
Am converting every element to string so as to use with jquery autocomplete.
Am using .map function to do this.
elements = elements.map(String);
output is
["5614", "6619", "7220", "7320", "7830", "8220", "73", "74", "75", "98", "149"]
Function is taking 0111,0112,0113,0142 all these values as Octal values and converting them to decimal.
I don't want this conversation and want to preserve leading Zero also , How can I do this , please help.
Function is taking 0111,0112,0113,0142 all these values as Octal values and converting them to decimal.
It's not the function doing that, it's this:
var elements=[5614,6619,7220,7320,7830,8220,0111,0112,0113,0142,0149]
In loose mode, if you start a number with a 0 followed by a series of octal digits, it's octal. That's why 010 === 8 is true:
console.log(010 === 8); // true
And heaven help us, but if you have a 0 followed by a number with non-octal decimal digits (8 or 9), it's decimal, which is why 011 === 09 and 9 === 09 are true:
console.log(011 === 09); // true
console.log(9 === 09); // true
The solution is:
Use strict mode ("use strict";). Both legacy octal literals (010) and legacy non-octal decimal literals (08) are disallowed in strict mode. (If you need to write octal, you can, with the newer 0o10 format — that's the number eight.)
Don't write leading zeros on numbers (with the possible exception of a 0 just prior to a . in a fractional number less than one)
You can't fix elements after the fact (because it's impossible to know, once they're numbers, which ones were incorrectly written in octal), you have to fix it at the point you're creating it, e.g.:
var elements=[5614,6619,7220,7320,7830,220,111,112,113,142,149]
This question already has answers here:
Javascript, why treated as octal
(6 answers)
Closed 7 years ago.
I am interesting in understanding why 032*2 returns 52 in JavaScript.
I have a feeling that 032 could be interpenetrated as octal notation but I could not find a proper reference to it.
Could you please:
Provide me an explanation with references.
Thanks in advance your help on this.
Numbers starting with 0 are Octal. So, 032 === 26.
To convert it into Base-10/Decimal number use parseInt with radix 10.
parseInt('032', 10) * 2; // 64
From MDN Docs:
If radix is undefined or 0 (or absent), JavaScript assumes the following:
If the input string begins with "0x" or "0X", radix is 16 (hexadecimal) and the remainder of the string is parsed.
If the input string begins with "0", radix is eight (octal) or 10 (decimal). Exactly which radix is chosen is implementation-dependent. ECMAScript 5 specifies that 10 (decimal) is used, but not all browsers support this yet. For this reason always specify a radix when using parseInt.
If the input string begins with any other value, the radix is 10 (decimal).
ECMAScript 5.1 specifies some extensions to Numeric literals in its annex:
The syntax and semantics of 7.8.3 [Numeric literals] can be extended as follows except that this extension is not allowed for strict mode code:
NumericLiteral ::
DecimalLiteral
HexIntegerLiteral
OctalIntegerLiteral
OctalIntegerLiteral ::
0 OctalDigit
OctalIntegerLiteral OctalDigit
This concludes that any number which starts with a 0 and is followed by OctalDigits can be considered an octal one. However, this is not allowed in strict mode.
Octal interpretations with no radix
Although discouraged by ECMAScript 3 and forbidden by ECMAScript 5,
many implementations interpret a numeric string beginning with a leading 0 as octal.The following may have an octal result, or it may have a decimal result.
Always specify a radix to avoid this unreliable behavior.
Source: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/parseInt
If you divide 11/10 in javascript you get 1.1. If you divide 011/10 in javascript you get 0.9. What causes the difference in results?
011 is an octal constant equal to 9.
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Values,_variables,_and_literals#Integers:
Integers can be expressed in decimal (base 10), hexadecimal (base 16), and octal (base 8).
Leading 0 (zero) on an integer literal indicates it is in octal. Octal integers can include only the digits 0-7.
Also note:
Octal integer literals are deprecated and have been removed from the ECMA-262, Edition 3 standard (in strict mode).
C++ also has octal constants.
If the number you are dealing with is represented as a string, you can specify the radix you want when casting it to a number by using parseInt().
+'011' // 9
parseInt('011') // 9
parseInt('011', 10) // 11
var x = 010;
console.log(x); //8
JS engine convert the number x to octal number. Why it happens? How can I prevent it?
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.
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.
JS treat numbers with leading zeros as octal only if they valid octal, if not then it treat it as decimal. To prevent this not use leading zeros in your source code
console.log(010, 10, +"010")
if (021 < 019) console.log('Paradox');
or use strict mode to not allow using leading zeros
'use strict'
if (021 < 019) console.log('Paradox');