何をしたいユーティリティか:「カンマ付与」
ここで作りたいのは、数値や数値っぽい文字列に「3 桁ごとのカンマ」を付けるユーティリティです。
1000 → 1,000
1234567 → 1,234,567
-9876543 → -9,876,543
金額だけでなく、「件数」「数量」「ID(数値)」など、業務画面ではとにかく数字が出てきます。
そのたびに毎回バラバラにフォーマットを書くのではなく、「カンマ付与はこの関数一択」という形にしておくと、コードも見た目も安定します。
カンマ付与の基本ルールを整理する
3 桁ごとに区切る、という約束
やりたいことはシンプルで、「整数部分を右から 3 桁ごとに区切る」ことです。
1 → 1
12 → 12
123 → 123
1234 → 1,234
12345 → 12,345
1234567 → 1,234,567
ここで大事なのは、「右から数える」ということです。
左から 3 桁ではなく、「末尾から 3 桁ずつ区切る」と覚えてください。
マイナス値も普通に出てくる
業務では、マイナスの数値もよく出てきます。
- 在庫差分
-10 - 売上差分
-5,000 - 調整額
-123,456
なので、符号(+/-)と数値部分を分けて考えるのがポイントになります。
一番シンプルな「カンマ付与」関数
数値・文字列どちらも受け取れる formatNumber
まずは、「整数を対象にしたカンマ付与」の基本形を作ります。
function formatNumber(value) {
if (value == null || value === "") {
return "";
}
const num = Number(value);
if (!Number.isFinite(num)) {
return "";
}
const sign = num < 0 ? "-" : "";
const absStr = Math.abs(num).toString();
const withComma = absStr.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return sign + withComma;
}
JavaScript重要なポイントを一つずつかみ砕く
1. null / 空文字は「何も表示しない」と決める
value == null は null と undefined の両方を拾います。
フォーム入力や API のレスポンスでは、null や "" が普通に混ざるので、
ここでは「値がないものは空文字を返す」という方針にしています。
業務によっては「0 を表示したい」ケースもあるので、そこはプロジェクトのルールで調整して構いません。
2. まずは Number に変換して「ちゃんとした数値か」確認する
const num = Number(value);
if (!Number.isFinite(num)) {
return "";
}
JavaScript"1000" のような文字列も受け入れたいので、一度 Number(...) で数値に変換します。NaN や Infinity のような「数値としておかしいもの」は、カンマ付与しても意味がないので、空文字を返すようにしています。
ここで「変な値は早めに弾く」ことで、後続の処理がシンプルになります。
3. 符号と絶対値を分けて扱う
const sign = num < 0 ? "-" : "";
const absStr = Math.abs(num).toString();
JavaScriptマイナス値を扱うときは、符号と絶対値を分けるのが鉄板です。
signには"-"または""を入れるabsStrには"1000"のような「符号なしの数字文字列」を入れる
カンマを入れるのは「絶対値の部分」だけにして、最後に符号をくっつける、という流れにすると、ロジックがとても分かりやすくなります。
4. 正規表現で 3 桁ごとにカンマを入れる
const withComma = absStr.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
JavaScriptここが一番「それっぽくて怖い」ところだと思うので、ちゃんと分解します。
\d{3} は「数字 3 桁」。(\d{3})+ は「数字 3 桁の塊が 1 回以上続く」。(?=...) は「先読み」といって、「この位置の右側がこうなっている場所」を探す。(?!\d) は「この先に数字が続かない位置」。\B は「単語境界ではない位置」(先頭にはマッチさせないための工夫)。
つまりこの正規表現は、ざっくり言うと、
「先頭以外で、右側に 3 桁の塊が続いていて、そのさらに右に数字が続かない位置」
を探して、そこにカンマを差し込んでいます。
結果として、
“1” → “1”
“12” → “12”
“123” → “123”
“1234” → “1,234”
“12345” → “12,345”
“1234567” → “1,234,567”
という、欲しい動きになります。
実際の動きを例で確認する
典型的なパターン
formatNumber(0); // "0"
formatNumber(10); // "10"
formatNumber(100); // "100"
formatNumber(1000); // "1,000"
formatNumber(1234567); // "1,234,567"
formatNumber(-9876543); // "-9,876,543"
JavaScript文字列として渡しても動く
formatNumber("1000"); // "1,000"
formatNumber("0012345"); // "12,345"
formatNumber("-5000"); // "-5,000"
JavaScriptNumber(...) で数値に変換しているので、
数値っぽい文字列であればそのまま扱えます。
小数を含む数値にカンマを付けたい場合
小数点を分けて考える
小数を含む数値にカンマを付けたい場合は、
「整数部分だけカンマ付与して、小数部分はそのまま残す」という考え方をします。
function formatNumberWithDecimal(value) {
if (value == null || value === "") {
return "";
}
const num = Number(value);
if (!Number.isFinite(num)) {
return "";
}
const sign = num < 0 ? "-" : "";
const absStr = Math.abs(num).toString();
const [intPart, fracPart = ""] = absStr.split(".");
const intWithComma = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
const result = fracPart ? intWithComma + "." + fracPart : intWithComma;
return sign + result;
}
JavaScriptどう動くかを確認する
formatNumberWithDecimal(1234.5); // "1,234.5"
formatNumberWithDecimal(1234.567); // "1,234.567"
formatNumberWithDecimal(-9876.5); // "-9,876.5"
formatNumberWithDecimal(1000); // "1,000"
JavaScript整数部分だけにカンマが入り、小数部分はそのまま残っているのが分かると思います。
金額フォーマットとの違いと使い分け
「カンマ付与」はもっと汎用的な役割
前にやった「金額フォーマット」は、
「金額としてどう見せるか(小数桁数、マイナス、通貨単位など)」まで含めたユーティリティでした。
今回の「カンマ付与」は、もっと素朴で、「とにかく 3 桁ごとにカンマを入れる」だけの役割です。
だからこそ、使い分けとしてはこうなります。
- 金額として見せたい →
formatCurrency(業務ルール込み) - 単に桁を読みやすくしたい →
formatNumber/formatNumberWithDecimal
例えば、「件数」「在庫数」「ID」などは formatNumber で十分なことが多いです。
設計として意識してほしいこと
「表示用」と「内部計算用」を絶対に混ぜない
カンマ付与した結果は、あくまで「表示用の文字列」です。
これをそのまま計算に使うと、確実にバグります。
const s = formatNumber(1000); // "1,000"
// これは絶対にやってはいけない
Number(s); // NaN になる
JavaScript計算は必ず「生の数値」で行い、
画面や帳票に出す直前で formatNumber を通す、という流れを徹底してください。
「カンマ付与のルール」を 1 箇所に閉じ込める
画面ごとにバラバラに
value.toLocaleString();
JavaScriptと書き始めると、ロケールや挙動の違いで見た目が揃わなくなります。
だからこそ、
export function formatNumber(value) { ... }
export function formatNumberWithDecimal(value) { ... }
JavaScriptのようなユーティリティを 1 箇所に置いて、
「数字を見せるときは必ずここを通す」
というルールにしておくと、
システム全体の見た目が一気に整います。
ちょっとだけ手を動かしてみる
コンソールで、次のあたりを試してみてください。
formatNumber(0);
formatNumber(1000);
formatNumber(1234567);
formatNumber(-9876543);
formatNumberWithDecimal(1234.5);
formatNumberWithDecimal(1234.567);
formatNumberWithDecimal(-9876.5);
JavaScript「どの値がどうフォーマットされるか」
「マイナスや小数がどう扱われるか」
を、自分の目で確認してみてください。
そのうえで、自分のプロジェクトに
export function formatNumber(value) { ... }
export function formatNumberWithDecimal(value) { ... }
JavaScriptを置いて、
数字を表示したくなったら、
生の value をそのまま出すのではなく、
必ずこの“カンマ付与ユーティリティ”を通す、という習慣をつけてみてください。
それだけで、あなたの業務画面の数字は、
「読みづらい生の数字」から、
一目で桁が分かる“業務レベルの数値表示”に変わっていきます。
