给数字添加千位分隔符

数值展示小要求:给页面中统计总数的数值添加一个千位分隔符。

虽然添加前和添加后都是一串数字,不过对于一个数量级较大(上亿级别)的数字,总不可能在读之前还从个位数开始数数(个十百千….),等你数到最后,领导已经走人了……有千位分隔符就很快让人知道最高位的什么级别(千、百万,十亿…)。

感受一下添加前后区别,视觉效果都感觉好很多。

添加前:123456789

添加后:123,456,789

看到这个需求首先想到遍历数字加逗号,,也就是就是一个一个数,从个位开始,每隔3个数字就加个逗号(,)。

遍历每个数字方案

当然我们需要把小数部分取出来,只对整数部分处理,因为小数是没有千分符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function readableNumber(value) {
const valueStr = value.toString();
const dotIdex = valueStr.indexOf('.');
let intValue = valueStr;
let floatValue = '';
// 1.把小数部分取出来
if (dotIdex !== -1) {
intValue = valueStr.substr(0, dotIdex);
floatValue = valueStr.substr(dotIdex + 1);
}
// 2.从个位开始每3位添加一个,
let newIntValue = '';
for (let index = 0; index < intValue.length; index++) {
const item = intValue[intValue.length - index - 1];
if (index !== 0 && index % 3 === 0) {
newIntValue = item + ',' + newIntValue;
} else {
newIntValue = item + newIntValue;
}
}
// 3.把小数部分添加回去
return floatValue ? newIntValue + '.' + floatValue : newIntValue;
}

看起来虽然很麻烦,但是很实用,也是很多人一般想到的方式,第2步的添加”,“也可以用其他的处理方式,不过大同小异,都是遍历方式。

看起来很多代码啊,有没更简单更高级用法?在很多情况下,使用正则表达式可以把问题简单化。

正则表达式方案

需要添加逗号(,),我们需要找到添加的位置,因此需要使用正则的捕获相关的语法,而添加,的位置有一定规则,不是所有的位置都加,,位置必须是从最右的个位开始,每隔三位开始加,因此我们需要使用正则的断言相关语法,断言捕获的位置必须满足这个规则。

了解了捕获和断言这两个知识点后,大概能写出以下的逻辑:

1
2
3
function readableNumber(value) {
return value.toString().replace(/(\d)(?=(\d{3})+(\.\d+)?$)/g, '$1,');
}

如果不需要考虑小数部分,正则可以写成/(\d)(?=(\d{3})+$)/g。是不是发现使用正则是真高效,少些好多代码。

虽然知道正则可以解决问题,但是不是一般人能到正则表达式的规则,简单还好,复杂一点的是完全没办法。大多数时候我们也做到读懂一个正则就不错了。那千分位还有其他方案吗?我不想写那么多代码。其实官方JavaScript标准也提供一个API来实现。

JavaScript标准API

JavaScript标准中定义的内置对象Number的原型上有个方法toLocaleString(),这个API也可实现添加千位分隔符,而且还很简单。

1
Number.prototype.toLocaleString([locales [, options]])

这个API方法上有两个可选的参数locales和options,可定制输出各种对数字的格式化实现。

这两个参数相关说明可以参考MDN

因此我的千位分隔符的处理函数又有第三种写法:

1
2
3
function readableNumber(value) {
return Number(value).toLocaleString();
}