ToolPal
深色背景上的数字与数学符号

JavaScript数字格式化完整指南:使用Intl.NumberFormat实现国际化

📷 Antoine Dautry / Pexels

JavaScript数字格式化完整指南:使用Intl.NumberFormat实现国际化

深入学习Intl.NumberFormat API,掌握货币、百分比、紧凑型数字的本地化显示方法,附实用JavaScript代码示例。

2026年4月10日3分钟阅读

在开发面向国际用户的Web应用时,数字显示往往是容易被忽视却很容易出问题的细节。我曾经就遇到过这种情况——产品上线后,德国用户反映数字看起来很奇怪,原来是小数点和千位分隔符用反了。

这个问题看似简单,实际上涉及到不同国家截然不同的数字书写习惯。幸运的是,JavaScript的Intl.NumberFormat API为我们提供了一个统一且强大的解决方案。

各国数字格式的差异

先来直观地感受一下问题所在。同一个数字1234567.89,在不同地区的标准写法是:

  • 中国 / 美国 / 日本: 1,234,567.89(逗号作千位分隔符,句点作小数点)
  • 德国 / 奥地利: 1.234.567,89(句点作千位分隔符,逗号作小数点)
  • 法国: 1 234 567,89(空格作千位分隔符,逗号作小数点)
  • 瑞士: 1'234'567.89(撇号作千位分隔符)
  • 印度: 12,34,567.89(独特的分组方式:首组3位,之后每组2位)

如果你用字符串拼接来手动处理这些格式,很快就会陷入无穷无尽的边界条件。Intl.NumberFormat就是为了解决这个问题而设计的。

Intl.NumberFormat基础用法

Intl是ES2015引入的国际化API集合,Intl.NumberFormat负责数字格式化。现代浏览器和Node.js 10+均支持,无需引入任何第三方库。

// 基本用法
const formatter = new Intl.NumberFormat('zh-CN');
formatter.format(1234567.89);
// "1,234,567.89"

// 德语格式
new Intl.NumberFormat('de-DE').format(1234567.89);
// "1.234.567,89"

// 法语格式
new Intl.NumberFormat('fr-FR').format(1234567.89);
// "1 234 567,89"

// 印地语(印度)
new Intl.NumberFormat('hi-IN').format(1234567.89);
// "12,34,567.89"

只需更改语言区域代码,就能自动应用该地区的格式规则,省去了大量手动处理的工作。

控制小数位数

// 固定保留2位小数
new Intl.NumberFormat('zh-CN', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
}).format(1234.5);
// "1,234.50"

// 最多3位小数,去掉末尾无效零
new Intl.NumberFormat('zh-CN', {
  minimumFractionDigits: 0,
  maximumFractionDigits: 3
}).format(1234.5);
// "1,234.5"

禁用千位分隔符

对于年份、ID等不需要千位分隔符的数字:

new Intl.NumberFormat('zh-CN', {
  useGrouping: false
}).format(2024);
// "2024"(不会显示成"2,024")

货币格式化

货币格式化是Intl.NumberFormat最常用的场景之一。不同货币的小数位数不同(人民币、日元等没有小数),货币符号的位置也各异。

// 人民币
new Intl.NumberFormat('zh-CN', {
  style: 'currency',
  currency: 'CNY'
}).format(1234.56);
// "¥1,234.56"

// 美元
new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).format(1234.56);
// "$1,234.56"

// 欧元(德语格式)
new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR'
}).format(1234.56);
// "1.234,56 €"

// 日元(无小数)
new Intl.NumberFormat('ja-JP', {
  style: 'currency',
  currency: 'JPY'
}).format(1234);
// "¥1,234"

关键点currency选项(货币种类)和语言区域(显示格式)是相互独立的。可以用中文格式显示美元:

new Intl.NumberFormat('zh-CN', {
  style: 'currency',
  currency: 'USD'
}).format(1234.56);
// "US$1,234.56"

货币显示方式的选择

const amount = 1234.56;

// 显示货币符号(默认)
new Intl.NumberFormat('zh-CN', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'symbol'
}).format(amount);
// "US$1,234.56"

// 显示ISO代码
new Intl.NumberFormat('zh-CN', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'code'
}).format(amount);
// "USD 1,234.56"

// 显示货币名称
new Intl.NumberFormat('zh-CN', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'name'
}).format(amount);
// "1,234.56美元"

currencyDisplay: 'name'在中文语言区域下会显示中文货币名称,这正是Intl API的强大之处。

注意:日元(JPY)、韩元(KRW)等没有小数单位的货币,使用currency样式时不会显示小数位,传入带小数的值会自动四舍五入。

百分比格式化

百分比格式化有一个容易踩的坑:

// 注意:传入小数形式(0.75表示75%)
new Intl.NumberFormat('zh-CN', {
  style: 'percent'
}).format(0.75);
// "75%"

// 指定小数位数
new Intl.NumberFormat('zh-CN', {
  style: 'percent',
  minimumFractionDigits: 1,
  maximumFractionDigits: 1
}).format(0.7523);
// "75.2%"

常见错误percent样式会将输入值乘以100。如果传入75,显示结果是7500%。如果你已有百分数值75,必须先除以100:

const percentValue = 75;
new Intl.NumberFormat('zh-CN', {
  style: 'percent'
}).format(percentValue / 100);
// "75%"

这个细节很多开发者首次使用时都会忽略,所以特别提醒一下。

科学计数法

科学和工程场景下的数值显示:

new Intl.NumberFormat('zh-CN', {
  notation: 'scientific'
}).format(1234567890);
// "1.235E9"

new Intl.NumberFormat('zh-CN', {
  notation: 'engineering'
}).format(1234567890);
// "1.235E9"(工程计数法保持指数为3的倍数)

紧凑型表示法(万、亿单位)

在数据看板和统计展示中,紧凑型表示非常实用。中文语言区域会自动使用万、亿等中文数量单位:

// 中文语言区域
new Intl.NumberFormat('zh-CN', {
  notation: 'compact'
}).format(10000);
// "1万"

new Intl.NumberFormat('zh-CN', {
  notation: 'compact'
}).format(35000000);
// "3500万"

new Intl.NumberFormat('zh-CN', {
  notation: 'compact'
}).format(1000000000);
// "10亿"

// 英语语言区域
new Intl.NumberFormat('en-US', {
  notation: 'compact'
}).format(1200);
// "1.2K"

// 日语语言区域
new Intl.NumberFormat('ja-JP', {
  notation: 'compact'
}).format(10000);
// "1万"

中文和日文使用万(10,000)作为基本计数单位,Intl.NumberFormat完整地支持了这一特性,无需自行实现。

常见陷阱与边界情况

NaN和Infinity的处理

new Intl.NumberFormat('zh-CN').format(NaN);
// "NaN"

new Intl.NumberFormat('zh-CN').format(Infinity);
// "∞"

建议在格式化前先验证数值有效性,避免向用户展示这些技术性符号。

性能优化:创建Intl.NumberFormat实例有一定开销,如果需要批量格式化,应复用同一实例:

// 低效写法
numbers.forEach(n => new Intl.NumberFormat('zh-CN').format(n));

// 高效写法
const formatter = new Intl.NumberFormat('zh-CN');
numbers.forEach(n => formatter.format(n));

formatToParts()方法:如果需要对格式化数字的各个部分分别处理(比如给货币符号单独设置样式):

new Intl.NumberFormat('zh-CN', {
  style: 'currency',
  currency: 'CNY'
}).formatToParts(1234.56);
// [
//   { type: 'currency', value: '¥' },
//   { type: 'integer', value: '1' },
//   { type: 'group', value: ',' },
//   { type: 'integer', value: '234' },
//   { type: 'decimal', value: '.' },
//   { type: 'fraction', value: '56' }
// ]

在React中,可以用这个方法对货币符号和数字部分应用不同的样式。

Intl.NumberFormat的局限性

坦白说,这个API也并非万能的:

  • 数字解析(反向操作):没有提供将本地化字符串解析回数字的功能。要把"1.234,56"转换成1234.56,需要自行实现。
  • 自定义格式字符串:不支持类似Excel的#,##0.00格式。有此类需求可以考虑numeral.js等库。
  • 会计格式:负数用括号表示的会计写法(如(1,234.56))通过currencySign: 'accounting'选项可以部分实现,但支持不完整。

对于大多数Web应用的实际需求,Intl.NumberFormat已经够用了。

使用Number Formatter在线工具

如果想不写代码就能快速测试各种格式化效果,可以使用ToolBox Hub的Number Formatter工具

  1. 在输入框中输入要格式化的数字
  2. 选择语言区域(支持30多种语言区域)
  3. 选择样式(decimal、currency、percent、scientific)
  4. 选择货币后会显示对应的货币符号
  5. 设置小数位数
  6. 选择是否启用千位分隔符
  7. 实时查看格式化结果,并可复制JavaScript代码

特别适合在部署前快速验证某个语言区域下数字的显示效果。

相关工具

总结

Intl.NumberFormat是JavaScript标准库中设计得相当出色的API。看似简单,实际上涵盖了货币、百分比、紧凑型表示等丰富功能。

核心要点回顾:

  • 面向用户的数字显示,务必使用Intl.NumberFormat
  • 货币代码与语言区域是独立的配置项
  • percent样式会乘以100,需传入小数形式
  • 中文语言区域的compact表示法自动支持万、亿单位
  • 批量格式化时复用同一实例以提升性能

在用户每天使用的应用中,数字显示的细节往往决定了产品的专业感。用好Intl.NumberFormat,让世界各地的用户都能看到符合本地习惯的数字格式。

常见问题

分享文章

XLinkedIn

相关文章