什么是千分位分隔

千位分隔符,其实就是数字中的逗号。当一个数字很大,位数很多时,人们很难一眼看出它的值。所以人们在数字中,每隔三位数加进一个逗号,也就是千位分隔符,以便更加容易认出数值。

假设有一个数字123456789.987654321,如果没有区分很难快速分辨出数值的大小。在进行千分位分隔后,它将被转换为 123,456,789.987,654,321。通过插入逗号作为分隔符,我们可以更容易地理解这个数值表示的是一个亿级别的数字。

千分位分隔广泛应用于金融、统计数据、货币金额等领域,以及在各种数据展示中。它可以使大数字更易读,并且更加美化和规范化。通过千分位分隔,我们可以方便地将数字转换为更具可读性的格式,使数据更加清晰和吸引人。

实现方案

在实际的应用场景中比如金融、货币金额,小数部分一般最多保留两位小数,所以以下实现的方案中都不对小数部分进行分隔。

方案一:传统方法遍历,将数字转为字符数组后,从低位向高位遍历,每三位添加一个分隔逗号。

function numberWithCommas(x) {
    // 转为字符串,按照.拆分
    let arr = (x + '').split(".");
    // 整数部分再拆分
    let int = arr[0].split('');
    // 保存小数部分
    const fraction = arr[1] || '';
    // 记录返回的结果
    let r = '';
    let len = int.length;
    
    // 倒序遍历
    int.reverse().forEach((v, i) => {
        // 非第一位且位值是3的倍数,添加','
        if(i !== 0 && i % 3 === 0) {
            r = v + ',' + r;
        } else {
            r = v + r;
        }
    })
    
    // 返回整数部分 + 小数部分
    return r + (!!fraction ? '.' + fraction : '');
}

// 使用示例
var number = 1234567.89;
var formattedNumber = numberWithCommas(number);
console.log(formattedNumber); // 输出: 1,234,567.89

方案二:使用正则表达式和字符串的replace方法来实现数值的千分位分隔。

function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

// 使用示例
var number = 1234567.89;
var formattedNumber = numberWithCommas(number);
console.log(formattedNumber); // 输出: 1,234,567.89

这个函数首先将数值转换为字符串,然后使用正则表达式\B(?=(\d{3})+(?!\d))来匹配所有数字之前的位置,这些位置之后有3个数字,并且这3个数字后面没有数字。然后,使用replace方法将这些位置替换为逗号。这样就形成了千分位分隔的字符串。

另一种正则匹配的方案,也比较简洁,先提取整数,使用replace第二个参数为函数替换的方式,在函数中进行二次匹配只处理整数部分。

function numberWithCommas(x) {
    var res = x.toString().replace(/\d+/, function (n) {
        return n.replace(/(\d)(?=(\d{3})+$)/g, function ($1) {
            return $1 + ",";
        });
    });
    return res;
}

这个函数提取整数后,对整数的部分匹配判断当前数字后边是否有3的倍数个数字,如果是,则把当前数字替换成当前数字+逗号。

方案三:使用国际化API Intl.NumberFormat对象。
Intl 对象是 ECMAScript 国际化 API 的一个命名空间,在这个对象下边提供了很多针对区域环境的设置方法,其中的Intl.NumberFormat对象能使数字在特定的语言环境下格式化。

var number = 1234567.8911111;
var formattedNumber = new Intl.NumberFormat('en-US', {}).format(number);
console.log(formattedNumber);  
// 1,234,567.891

默认小数就显示3位,可以设置显示的位数。

var number = 1234567.8911111;
var formattedNumber = new Intl.NumberFormat('en-US', {
    maximumFractionDigits:10  
}).format(number);
console.log(formattedNumber);  
// 1,234,567.8911111

这个方法兼容性出奇的好,我们可以放心使用。
Intl.NumberFormat.format兼容性.jpg

maximumFractionDigits选项设置兼容性:
Intl.NumberFormat maximumFractionDigits兼容性.jpg

方案四:使用toLocaleString()方法。
这个返回数字特定于语言环境的表示字符串。如果浏览器实现了Intl.NumberFormat API,那么这个方法就会调用Intl.NumberFormat来返回格式化结果。

console.log((1234567.8911111).toLocaleString('en-US'));  
// 1,234,567.891

console.log((1234567.8911111).toLocaleString('en-US', {
    maximumFractionDigits:10
})); 
// 1,234,567.8911111

结语

使用千分位分隔数字,能让数字具有较强的可读性。上边介绍的四种方案,第一种比较笨拙,实现过程比较繁琐;第二种用了正则,代码清爽简洁,瞬间提升了N个档次;第三种JS原生支持数据格式化,是趋于标准的实现方式,理论上说我们更应该拥抱标准,更多的使用原生实现去替换各种Hack代码;第四种和第三种一样,如果不熟悉国际化API Intl.NumberFormat对象时,可以使用这种方式作为替代。