JavaScriptで数値を扱う際、多くの開発者は日常的に10進数を利用しています。
しかし、低レイヤーの処理や特定のシステム連携において、8進数(オクタール)を扱う必要が生じることがあります。
かつてのJavaScriptでは8進数の書き方が曖昧であり、バグの原因となることも少なくありませんでした。
現在のモダンなJavaScriptでは、明確で安全な新しい表記法が導入されています。
本記事では、JavaScriptにおける8進数リテラルの正しい記述方法や、数値変換の基本、そして実務での活用シーンについて詳しく紹介します。
8進数リテラルの基本と新しい標準
JavaScriptにおいて8進数を直接プログラム内に記述する場合、現在は「0o」というプレフィックスを使用します。
この表記法はES6(ECMAScript 2015)で導入され、現在の開発現場における標準的な書き方として定着しています。
「0o」または「0O」による表記
8進数リテラルを作成するには、数値の先頭に「0o(ゼロと小文字のオー)」または「0O(ゼロと大文字のオー)」を付与します。
一般的には、数字の「0」と区別がつきやすいように、小文字の「0o」を使用することが推奨されています。
以下のコード例で、具体的な書き方を確認してみましょう。
// 8進数のリテラル表記
const octalValue = 0o10; // 8進数の10は、10進数で「8」
console.log(octalValue);
8
このように、コード上で「0o10」と記述すると、JavaScriptエンジンはそれを8進数として解釈し、内部的には10進数の「8」として保持します。
レガシーな表記法(0始まり)の問題点
古いJavaScript(ES5以前)では、先頭に「0」を付けるだけで8進数として扱うことが可能でした。
例えば、「010」と記述すると、自動的に10進数の「8」として処理される仕組みです。
しかし、この表記法は非常に紛らわしく、開発者が意図せずに数値を書き換えてしまう重大なリスクを孕んでいました。
そのため、モダンなJavaScriptのStrictモード(”use strict”;)環境では、この古い表記法は禁止されています。
"use strict";
// Strictモードでは先頭が0の数値はエラーになる
const legacyOctal = 010;
Uncaught SyntaxError: Octal literals are not allowed in strict mode.
エラーを回避し、コードの可読性を高めるためにも、必ず「0o」を使用するようにしましょう。
8進数で利用可能な数字と構文ルール
8進数はその名の通り、8つの数字(0から7まで)を用いて数値を表現する仕組みです。
したがって、8進数リテラルの中に「8」や「9」といった数字を含めることはできません。
数値の範囲に関するエラー
「0o」から始まる数値の中に、範囲外の数字が含まれている場合、JavaScriptは実行前に構文エラーを発生させます。
プログラムを実行する前にエディタやコンパイラが警告を出してくれるため、比較的発見しやすいミスと言えるでしょう。
// 8進数に「8」は存在しないため、構文エラー
const invalidOctal = 0o18;
Uncaught SyntaxError: Invalid or unexpected token
このように、使用できるのは0〜7の範囲内だけであるという点を常に意識しておく必要があります。
大文字と小文字の使い分け
前述の通り、「0o」と「0O」はどちらも機能的には同じですが、可読性の観点からは小文字が選ばれます。
大文字の「O」は、フォントによっては数字の「0」と見間違える可能性が高いためです。
チーム開発においては、Prettierなどのコード整形ツールを用いて小文字に統一するのが一般的です。
10進数から8進数へ変換する方法
プログラムの実行中に、動的に数値を8進数の形式に変換したい場合があります。
JavaScriptでは、Number.prototype.toString()メソッドを活用することで、簡単にこの変換を実現できます。
toString(8)の活用
toString()メソッドは、引数に基数(ラジックス)を指定することで、その進数に基づいた文字列を返します。
8進数へ変換したい場合は、引数に「8」を渡します。
const decimalNum = 64;
// 10進数の64を8進数の文字列に変換
const octalString = decimalNum.toString(8);
console.log(octalString);
console.log(typeof octalString);
100
string
返される結果は数値型ではなく文字列型(String)である点に注意してください。
計算に使用するのではなく、表示用やデータ転送用のフォーマットとして利用されます。
8進数から10進数へ変換する方法
外部から受け取った8進数の文字列を、JavaScriptで計算可能な10進数の数値に戻す処理も重要です。
これには、グローバル関数のparseInt()、あるいはNumber()コンストラクタを使用します。
parseInt関数による変換
parseInt()は、第2引数に解析したい基数を指定できます。
文字列が「0o」で始まっていない場合でも、第2引数に「8」を指定すれば強制的に8進数として解析します。
const octalStr = "755";
// 第2引数に8を指定して解析
const result = parseInt(octalStr, 8);
console.log(result);
493
parseIntを使用する際は、常に基数を明示することが推奨されます。
基数を省略すると、ブラウザのバージョンや実行環境によって予期せぬ解釈がなされる恐れがあるためです。
Number関数と0oの組み合わせ
文字列自体に「0o」が含まれている場合は、Number()関数にそのまま渡すだけで自動的に10進数へ変換されます。
const formattedOctal = "0o10";
// プレフィックスがあればNumber()で自動判別
console.log(Number(formattedOctal));
8
データソースがどのような形式で8進数を保持しているかに合わせて、適切な変換手法を選択しましょう。
実務における8進数の活用例
日常的なWeb開発で8進数を直接扱う機会は少ないかもしれませんが、特定の分野では非常に重要な役割を果たします。
ファイルパーミッション(権限)の管理
Unix系システムにおけるファイルの読み取り・書き込み・実行権限(パーミッション)は、一般的に3桁の8進数で表現されます。
例えば「755」や「644」といった数値が有名です。
Node.jsなどでファイルシステムを操作する際、これらの数値を8進数リテラルで記述すると直感的になります。
const fs = require('fs');
// 0o755 は rwxr-xr-x 権限を意味する
fs.chmodSync('example.txt', 0o755);
このように、数値の背景にある意味(ビットフラグなど)が8進数と結びついている場合に有効です。
特殊なエスケープシーケンス
文字列の中で特定の文字を表現するために、8進数エスケープシーケンスが使われることがあります。
ただし、現代のJavaScriptではUnicode(\uXXXX)の使用が推奨されており、8進数エスケープは非推奨または制限されていることが多いです。
古いソースコードをメンテナンスする際に、「\」の後に数字が続く形式を見かけたら、それは8進数として処理されている可能性があります。
数値変換と比較の注意点
8進数を扱う上で、開発者がハマりやすいポイントがいくつか存在します。
以下の比較表で、よく使われる進数とその特徴を整理しました。
| 進数 | プレフィックス | 利用可能な数字 | 主な用途 |
|---|---|---|---|
| 2進数 | 0b | 0, 1 | フラグ管理、ビット演算 |
| 8進数 | 0o | 0 – 7 | パーミッション、古いデータ変換 |
| 10進数 | なし | 0 – 9 | 一般的な計算 |
| 16進数 | 0x | 0 – 9, A – F | カラーコード、メモリ番地 |
JavaScriptの内部では、どのような進数で記述しても最終的には同じNumber型として数値が保持されます。
そのため、0o10 === 8 という比較は true になります。
あくまで「ソースコード上での見た目」と「入出力の形式」が進数によって変わるだけであると理解しておきましょう。
エラーを防ぐためのベストプラクティス
意図しない計算ミスを防ぐために、以下の3つのルールを徹底しましょう。
1. 古い「0」始まりの表記を完全に排除する
プロジェクト全体のESLintルールなどで、レガシーな8進数リテラルを禁止設定にしましょう。
これにより、010 と書いてしまった瞬間にエラーとして検知でき、バグの混入を未然に防げます。
2. 文字列解析には必ず基数を指定する
parseInt(value, 8) のように、常に基数を第2引数に含める習慣をつけましょう。
これにより、文字列の先頭文字に左右されない堅牢な変換ロジックを構築できます。
3. 数値の可読性を重視する
もし8進数を使う必要がない場面であれば、無理に使用せず10進数に書き換えるべきです。
どうしても8進数が必要な場合は、コメントを添えて「なぜ8進数で記述しているのか」を後続のエンジニアに伝えるようにしましょう。
まとめ
JavaScriptにおける8進数は、かつての曖昧な仕様から、現在の「0o」プレフィックスによる明確な仕様へと進化を遂げました。
Strictモードの普及により、古い「0」から始まる表記は過去のものとなり、より安全なプログラミングが可能になっています。
toString(8) や parseInt(str, 8) といった変換メソッドを正しく使い分けることで、データのやり取りもスムーズに行えるでしょう。
ファイル権限の操作やビット演算が絡む開発において、8進数の知識は大きな武器となります。
今回解説した正しい書き方と変換ルールを、ぜひ日々の開発に役立ててください。
