JavaScriptで2進数を入力できるか調べるためにchromeのコンソールを立ち上げて0011と入力したときに、自分が予想してた値は3でしたが出力された値は9でした。
ここで9が出力されることを普通に知っていた方は本記事は対象外となっております。。
> 0011
< 9 //予想では3
他にも0010や0100を入力してみてどうやらJavaScriptでは数字の頭に0をつけると入力した数値を8進数として解析し、10進数として出力される仕様があるのだろうという予想ができました。
> 0010
< 8
> 0100
< 64
ではなぜ頭に0をつけると8進数として解析されるのか?
結局2進数としては解析できないのだろうか?
という疑問を抱きMDNに飛んで調べて見ました。
以下調べた概要をまとめます。
数値リテラル(Numeric Literal)
概要
- JavaScriptの整数は10進数、2進数、8進数、16進数で表現することができます。
- 2進数は
0b,0Bから始まり 後に続く0と1で構成されます。 - 8進数は
0o,0Oまたは0から始まり、後に続く0から7の数値で構成されます。 - 16進数は
0x,0Xから始まり、後に続く数字 (0から9) とaからfおよびAからFのアルファベットで構成されます。
10進数(Decimal)
- 先頭が0 (ゼロ) ではない一連の数字で構成されます。
- 先頭のゼロに続く数字が8以上の時、10進数として解析されます。
※この先頭が0の時の挙動に関してはこちらに詳細が載っているっぽいです。
> 12345678
< 12345678 //通常の10進数
> 0888
< 888 //10進数として解析され888として出力されます
> 0777
< 511 //8進数として解析され10進数の511が出力されます。
2進数(Binary:0b,0Bから始まる)
- 先頭ゼロに続いて、小文字または大文字のラテン文字
B(0bまたは0B)を使用します。 - この仕様はECMAScript2015から新しくサポートされている仕様です。
-
0b後の数字が0または1でない場合SyntaxErrorがスローされます。
> 0b00010101 //bが小文字
< 21
> 0B00011011 //bが大文字
< 27
> 0b00000002 //0bのあとに0,1以外の数値
< Uncaught SyntaxError: Invalid or unexpected token //例外をスロー
8進数(Octal:0o,0Oから始まる)
- 先頭ゼロに続いて、小文字または大文字のラテン文字'O' (
0oまたは0O)を使用します。 - 先頭ゼロに続く数値が0から7の場合も8進数として解析されます。
- この仕様はECMAScript2015から新しくサポートされている仕様です。
-
0o後の数字が範囲外(01234567) の場合SyntaxErrorがスローされます。
> 0o644 //oが小文字
< 420
> 0O755 //oが大文字
< 493
> 0o1238 //0oの後に01234567以外の数値
< Uncaught SyntaxError: Invalid or unexpected token //例外をスロー
16進数(Hexadecimal:0x,0Xから始まる)
- 先頭ゼロに続いて、小文字または大文字のラテン文字
X(0xまたは0X)を使用します。 -
0xの後の数字が範囲外(0123456789ABCDEF(abcdef))の場合SyntaxErrorがスローされます。
> 0xFFFFFFFFFFFFFFFFF
< 295147905179352830000 //xが小文字
> 0X123456789ABCDEF
< 81985529216486900 //xが大文字
> 0XA
< 10
> 0xG1234
< Uncaught SyntaxError: Invalid or unexpected token //例外をスロー
参考
最後に
JavaScriptではまだまだ知っている仕様よりも知らない仕様の方が多いと思いますが、こういう勘違いがきっかけでも正しい仕様を少しずつ覚えていければと。