何をしたいユーティリティか:「通貨変換表示」
ここで目指すのは、単に「金額にカンマを付ける」だけではなく、
「通貨単位や通貨コードを付けて、人間が見て意味が分かる形で表示する」ユーティリティです。
たとえば、次のような表示を安定して出したいイメージです。
formatCurrencyDisplay(1234567, "JPY"); // "¥1,234,567"
formatCurrencyDisplay(1234.5, "USD"); // "$1,234.50"
formatCurrencyDisplay(99.9, "EUR"); // "€99.90"
JavaScriptさらに、為替レートを使って「円 → ドル」のような通貨変換を行い、その結果を表示用に整えるところまでを、ひとまとまりのユーティリティとして考えていきます。
「通貨変換表示」を分解して考える
通貨変換表示は、実は三つのステップに分解できます。
一つ目は、元の金額を別の通貨に変換することです。
二つ目は、変換後の数値を「金額として」フォーマットすることです。
三つ目は、通貨記号や通貨コードを付けて、最終的な文字列にすることです。
この三つを毎回バラバラに書くのではなく、「変換」と「表示」を小さな関数に分けておくと、業務コードがかなり読みやすくなります。
まずは「通貨記号付きの表示」だけを作る
最初に、為替変換は置いておいて、「ある通貨の金額をきれいに表示する」関数から作ります。
ここでは、通貨コードごとに簡単な記号マップを用意し、整数部分はカンマ区切り、小数は任意の桁数で揃える、というルールにします。
const CURRENCY_SYMBOLS = {
JPY: "¥",
USD: "$",
EUR: "€",
};
function formatCurrencyDisplay(amount, currencyCode = "JPY", options = {}) {
const { fractionDigits = null } = options;
if (amount == null || amount === "") {
return "";
}
const num = Number(amount);
if (!Number.isFinite(num)) {
return "";
}
const sign = num < 0 ? "-" : "";
const absNum = Math.abs(num);
let intPartStr;
let fracPartStr = "";
if (fractionDigits == null) {
const [intStr, fracStr = ""] = absNum.toString().split(".");
intPartStr = intStr;
fracPartStr = fracStr;
} else {
const fixed = absNum.toFixed(fractionDigits);
const [intStr, fracStr = ""] = fixed.split(".");
intPartStr = intStr;
fracPartStr = fracStr;
}
const intWithComma = intPartStr.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
const numberPart =
fracPartStr && fractionDigits !== 0
? intWithComma + "." + fracPartStr
: intWithComma;
const symbol = CURRENCY_SYMBOLS[currencyCode] ?? "";
const codeSuffix = symbol ? "" : ` ${currencyCode}`;
return sign + symbol + numberPart + codeSuffix;
}
JavaScriptこの関数のポイントを、初心者向けにかみ砕いて説明します。
通貨表示関数の重要ポイントを深掘りする
最初に、値のチェックと数値変換をしています。
if (amount == null || amount === "") {
return "";
}
const num = Number(amount);
if (!Number.isFinite(num)) {
return "";
}
JavaScriptここでは「値がない」「数値としておかしい」ものは、表示しない(空文字)という方針にしています。
業務画面では、null や空文字が混ざることが多いので、早めに弾いておくと後の処理がシンプルになります。
次に、マイナスの扱いです。
const sign = num < 0 ? "-" : "";
const absNum = Math.abs(num);
JavaScript符号と絶対値を分けておくことで、「カンマ付与や小数処理は絶対値に対してだけ行う」というシンプルな構造にできます。最後に符号をくっつけるだけなので、マイナスでもロジックが崩れません。
小数の扱いは、オプションの fractionDigits で切り替えています。
if (fractionDigits == null) {
const [intStr, fracStr = ""] = absNum.toString().split(".");
intPartStr = intStr;
fracPartStr = fracStr;
} else {
const fixed = absNum.toFixed(fractionDigits);
const [intStr, fracStr = ""] = fixed.split(".");
intPartStr = intStr;
fracPartStr = fracStr;
}
JavaScriptfractionDigits が null のときは、元の数値の小数をそのまま使います。fractionDigits に 0 以上の整数を渡したときは、toFixed で丸めて、小数桁数を揃えます。
たとえば、次のような動きになります。
formatCurrencyDisplay(1234.5, "USD"); // "$1,234.5"
formatCurrencyDisplay(1234.5, "USD", { fractionDigits: 2 }); // "$1,234.50"
formatCurrencyDisplay(1234, "USD", { fractionDigits: 2 }); // "$1,234.00"
JavaScript整数部分へのカンマ付与は、以前やったものと同じ正規表現です。
const intWithComma = intPartStr.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
JavaScriptこれで「右から 3 桁ごとにカンマ」が入ります。
最後に、通貨記号と通貨コードを組み立てます。
const symbol = CURRENCY_SYMBOLS[currencyCode] ?? "";
const codeSuffix = symbol ? "" : ` ${currencyCode}`;
return sign + symbol + numberPart + codeSuffix;
JavaScriptここでは、通貨コードに対応する記号がマップにあればそれを使い、なければ記号なしで " USD" のようにコードを後ろに付ける、という挙動にしています。
たとえば、次のような結果になります。
formatCurrencyDisplay(1234567, "JPY"); // "¥1,234,567"
formatCurrencyDisplay(1234.5, "USD"); // "$1,234.5"
formatCurrencyDisplay(99.9, "EUR", { fractionDigits: 2 }); // "€99.90"
formatCurrencyDisplay(500, "AUD"); // "500 AUD"(記号がないのでコードを後ろに)
JavaScript為替レートを使った「通貨変換+表示」
次に、「円をドルに変換して、その結果を表示する」ようなユーティリティを考えます。
ここでは、為替レートは外から渡す前提にして、「変換」と「表示」を分けて実装します。
function convertCurrency(amount, rate) {
if (amount == null || amount === "") {
return null;
}
const num = Number(amount);
if (!Number.isFinite(num)) {
return null;
}
const r = Number(rate);
if (!Number.isFinite(r)) {
return null;
}
return num * r;
}
JavaScriptこの関数は、「元の金額」と「レート」を掛け算するだけの、とても素朴なものです。
大事なのは、「変換の責務」と「表示の責務」を分けていることです。
これを使って、「円 → ドル」の変換表示を行う関数を書いてみます。
function convertAndFormat(amount, fromCode, toCode, rate, options = {}) {
const converted = convertCurrency(amount, rate);
if (converted == null) {
return "";
}
return formatCurrencyDisplay(converted, toCode, options);
}
JavaScript使い方の例は次の通りです。
const rateJpyToUsd = 0.0075; // 例: 1 JPY = 0.0075 USD とする
convertAndFormat(100000, "JPY", "USD", rateJpyToUsd, { fractionDigits: 2 });
// "$750.00"
convertAndFormat(1234567, "JPY", "USD", rateJpyToUsd, { fractionDigits: 2 });
// "$9,259.25"(例のレートの場合)
JavaScriptここでのポイントは、「どこでレートを決めるか」「どこで表示ルールを決めるか」を分けていることです。
レートの取得や更新は別の層(API や設定)に任せて、ユーティリティは「掛け算」と「フォーマット」だけに集中させると、テストしやすくなります。
Intl.NumberFormat を使う選択肢も知っておく
ブラウザや Node.js には、Intl.NumberFormat という国際化対応のフォーマッタが用意されています。
これを使うと、通貨表示をかなり簡単に書けます。
function formatCurrencyIntl(amount, currencyCode = "JPY", locale = "ja-JP") {
if (amount == null || amount === "") {
return "";
}
const num = Number(amount);
if (!Number.isFinite(num)) {
return "";
}
return new Intl.NumberFormat(locale, {
style: "currency",
currency: currencyCode,
}).format(num);
}
JavaScriptたとえば、次のように動きます。
formatCurrencyIntl(1234567, "JPY", "ja-JP"); // "¥1,234,567"
formatCurrencyIntl(1234.5, "USD", "en-US"); // "$1,234.50"
formatCurrencyIntl(99.9, "EUR", "de-DE"); // "99,90 €"
JavaScriptただし、Intl.NumberFormat はロケールによって記号の位置や小数点の記号が変わるため、「システム全体で完全に同じ見た目にしたい」という要件が強い場合は、先ほどのように自前でルールを決めたユーティリティを使う方がコントロールしやすいです。
実務で意識してほしい設計のポイント
一つ目は、「計算用の値」と「表示用の文字列」を絶対に混ぜないことです。
通貨変換は数値で行い、画面や帳票に出す直前でフォーマット関数を通して文字列にする、という流れを徹底してください。
二つ目は、「通貨表示のルール」を一箇所に閉じ込めることです。
画面ごとにバラバラに "¥" + value.toLocaleString() のようなコードを書き始めると、必ずどこかで表記揺れが起きます。formatCurrencyDisplay や convertAndFormat のような関数をモジュールにまとめ、「通貨を見せるときは必ずここを通す」と決めてしまうと、システム全体の見た目が一気に整います。
三つ目は、「変換」と「表示」を分けることです。
レートの取得や更新は別の層に任せ、ユーティリティは「掛け算」と「フォーマット」だけに集中させると、テストしやすく、バグの原因も追いやすくなります。
少し手を動かして感覚をつかむ
コンソールで、次のようなコードを実際に打ってみてください。
formatCurrencyDisplay(1234567, "JPY");
formatCurrencyDisplay(1234.5, "USD", { fractionDigits: 2 });
formatCurrencyDisplay(-98765.4321, "EUR", { fractionDigits: 2 });
const rateJpyToUsd = 0.0075;
convertAndFormat(100000, "JPY", "USD", rateJpyToUsd, { fractionDigits: 2 });
convertAndFormat(1234567, "JPY", "USD", rateJpyToUsd, { fractionDigits: 2 });
formatCurrencyIntl(1234567, "JPY", "ja-JP");
formatCurrencyIntl(1234.5, "USD", "en-US");
JavaScriptどのような文字列が返ってくるかを眺めながら、「変換」と「表示」が頭の中で分かれている感覚をつかんでみてください。
そのうえで、自分のプロジェクトに
export function formatCurrencyDisplay(...) { ... }
export function convertCurrency(...) { ... }
export function convertAndFormat(...) { ... }
JavaScriptのような関数を置き、「通貨を扱うときは必ずここを通す」というルールを作ってみてください。
それだけで、あなたのシステムの通貨表示は、場当たり的な文字列連結から、意図と一貫性を備えた「業務レベルの通貨変換表示ユーティリティ」に変わっていきます。
