ほぼすべてのブラウザやNode.jsでサポートされている数値をフォーマットするAPI「Intl.NumberFormat」を紹介する記事です。
JavaScriptで数値をカンマ区切りにしたいときにGoogleで検索してみると、正規表現を使っていたり、ループで回して3桁ごとにカンマ付ける実装を紹介する記事を多く見つけました。
しかし、それらは古い記事ということもあり、2018年現在は数値のフォーマットを実装する必要はありません。EcmaScriptで仕様策定されておりほとんどのブラウザやNode.jsで使える関数があるので紹介します。
今回紹介するコードの実行結果はすべてChromeでの結果になります。
TL;DR
- 「Intl.NumberFormat.prototype.format」を使います。
- まだChromeとFirefoxだけですが、「Intl.NumberFormat.prototype.formatToParts」を使うとカスタムフォーマットもできます。
Intl
i18nやl10nといった国際化対応するためのAPIです。
詳しくは「Intl - JavaScript|MDN」をお読みください。
EcmaScriptの仕様については「ここ」を読んで下さい。
Intl.NumberFormat
通過や文字など国や地域によって数の表記は違います。このAPIはその国ごとの表記を指定した表記に変換してくれるAPIを提供してくれるオブジェクトです。
詳しくはMDNの記事をお読み下さい。日本語の記事は情報が古いので英語版を参考にしてください。
以下のようにlocaleをコンストラクタの引数に指定することができます。
引数の指定が無い場合は'us-EN'
が設定されます。
const formatter = new Intl.NumberFormat('ja-JP');
Intl.NumberFormat.prototype.format
数値を変換する関数です。Intl.NumberFormatのメソッドです。
IEを含むほぼすべてのブラウザで使用可能です。
よく使われそうな例を紹介します。
カンマ区切り
冒頭で説明したカンマ区切りです。3桁ごとに区切って表示する場合に使うことができます。
以下は'ja-JP'
を指定していますが、'us-EN'
や引数なしでも同じように3桁でカンマ区切りします。
const formatter = new Intl.NumberFormat('ja-JP');
formatter.format(1000);
// => "1,000"
通貨
数値をサクッと円やドル表記したいことはあると思います。
円の表記は以下のようにNumberFormatの第2引数にオブジェクトを渡すことで実現可能です。
第2引数のオプションについてもやはりMDNの「Intl.NumberFormat」に詳しく載っていますので興味ある方はそちらをお読み下さい。
const formatter = new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY'
});
formatter.format(1000);
// => "¥1,000"
もちろん、ドルやユーロなども対応しています。
let formatter = new Intl.NumberFormat('us-EN', {
style: 'currency',
currency: 'USD'
});
formatter.format(1000);
// => "$1,000.00"
let formatter = new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR'
});
formatter.format(1000)
// => "1.000,00 €"
漢数字
数値を漢数字の文字列に変換することも可能です。
以下は「中国で使用される簡体字で書かれる中国語の10進数の漢数字」という指定をしています。
zh-Hans-CN
までが「中国で使用される簡体字で書かれる中国語」を指し、u-nu-hanidec
が「10進数の漢数字」を指します。
const formatter = new Intl.NumberFormat('zh-Hans-CN-u-nu-hanidec');
formatter.format(1234567890);
// => "一,二三四,五六七,八九〇"
Intl.NumberFormat.prototype.formatToParts
上記のようにformat
関数で数値のフォーマットが行えますが、新しいAPIであるformatToParts
に関しても紹介しておきます。
執筆時点(2018/04/15)ではChrome63とFirefox58で使えるようになっています。
Node.jsも次期バージョンのv10では使えます。
EcmaScriptの仕様は「ここ」にあります。
数値のカスタムフォーマットを行うことが可能になります。
formatToParts
の戻り値は{type: string, value: string}のオブジェクトの配列です。
const formatter = new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY'
});
formatter.formatToParts(1000);
// => [ { type: 'currency', value: '¥' },
// { type: 'integer', value: '1' },
// { type: 'group', value: ',' },
// { type: 'integer', value: '000' } ]
オブジェクトの配列なので、あとは好き勝手いじることが可能です。
以下はMDNに掲載されている例をJPYにしてみた例です。
const num = 1000;
const formatter = new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY'
});
const yen = formatter.formatToParts(num).map(({type, value}) => {
switch (type) {
case 'currency': return "<strong>" + value + "</strong>";
default: return value;
}
}).reduce((string, part) => {return string + part});
console.log(yen);
// => "<strong>¥</strong>1,000"
最後に
数値のフォーマット関数は標準で用意されているAPIを使いましょう。
補足(2018/04/17)
はてブでSafariで使えないというコメントがあったので補足します。
Intl.NumberFormat.prototype.formatはSafari10から対応しています。
Intl.NumberFormat.prototype.formatToPartsは使えません。
MDNの日本語版のブラウザ対応表が更新されていませんでした。英語版では10から対応と記載がありました。Safari11.1でも確認済みです。
また、MDNのIntl.NumberFormat.prototype.formatの日本語版のSafariのサポートバージョンも更新しておきました。
参考
最後までお読みいただきありがとうございました。不備や質問がございましたらコメント欄に記載またはTwitterで @shisama_ 宛にメンション飛ばして下さい。