JS中的数字格式化和大位数缩写

以前因为项目需要 i18n ,一直以来都是自己写了一个格式化函数来处理,会使用 replace 配合正则对数字进行千位分割来展示,并且搭配 Vue.filter 来实现快速格式化。
但是对于大位数处理就会比较麻烦了,因为在境内就需要使用 万位分割,大位数使用 万、亿、万亿 来缩,而在英语系国家就会使用 千分分隔,比如说: K、M、B 来缩写数额。

正巧最近开始了一个需要国际化的项目,在一开始编写数字格式化过滤器的时候偶尔发现了 Intl.NumberFormat().format() 这个API,原来现在 原生JS就支持了对数字的格式化,并且不光可以千位分隔,还可以将大位数缩写。

简单的看一下这个API:

Intl.NumberFormat 是对语言敏感的格式化数字类的构造器类。
语法:
new Intl.NumberFormat([locales[, options]])

是不是很简单,并且可以从参数中看到,这个API是支持设置本地化的,那就快速来过一遍示例:

// 直接格式化
new Intl.NumberFormat().format(123456789)
// ’123,456,789

使用 locales 本地化数字:

// 英语环境下的数字格式化
new Intl.NumberFormat('en').format(123456.789);
// '123,456.789'
// 中文环境下的数字格式化
new Intl.NumberFormat('zh').format(123456.789);
// '123,456.789'
// 德语环境使用逗号(,)作为小数点,使用句号(.)作为千位分隔符
new Intl.NumberFormat('de-DE').format(123456.789)
// '123.456,789'
// 阿拉伯语国家使用阿拉伯语数字
new Intl.NumberFormat('ar-EG').format(123456.789);
// '١٢٣٬٤٥٦٫٧٨٩'

配置紧凑型({notation:"compact"}) 可以将大位数缩写:

new Intl.NumberFormat('en', {notation:"compact"}).format(123456789)
// '123M'
new Intl.NumberFormat('en', {notation:"compact", compactDisplay: "long"}).format(123456789)
// '123 million'
new Intl.NumberFormat('zh', {notation:"compact"}).format(123456789)
// '1.2亿'
new Intl.NumberFormat('zh', {notation:"compact", compactDisplay: "long"}).format(123456789)
// '1.2亿'
new Intl.NumberFormat('zh-Hans-CN-u-nu-hanidec', {notation: "compact"}).format(123456789)
// 一.二亿
new Intl.NumberFormat('zh-Hans-CN-u-nu-hanidec', {notation: "compact"}).format(1234567890)
// '一二亿'

可以看到使用中文十进制数字,还是稍微有点问题的,不过直接使用阿拉伯数字展示也不是不行对吧。

其他扩展用法查看MDN的文档就行,里面有详细的示例,我就不一一举例了。

😫 关于兼容性

兼容性问题是有很多人关注的,作为一个在2012年被提出的规范(ECMA-402 1.0),从 IE 11 开始被支持(不持支大位数缩写),其它的现代浏览器都是支持的,当然处在实验阶段的属性实现程度不一致,不过 formatlocales 以及 notation 都是支持的,所以正常使用已经足够了。


📚 参考文档:

Intl.NumberFormat - JavaScript | MDN
Intl.NumberFormat.prototype.format() - JavaScript | MDN
Intl.NumberFormat.prototype.format - ECMAScript Internationalization API Specification – ECMA-402 Edition 1.0