今天在看vuex的demo时,看到引用了一个currency脚本文件,通过仔细分析其中的代码,发现其主要作用就是进行数值千分位的处理。现简要梳理一下从这个脚本中学习吸收到的东西。
场景:

进行js中数字的整数部分千分位划分

input:1234.56478
output:1,234.5678

先说说大体的实现思路,先将该数字转换成字符串,获取整数部分,然后将整数部分进行每3位的划分,之后再将千分位后的整数部分与小数部分拼接。其中的难点就在于整数部分的千分位划分上。

currency脚本中的处理方法是,使用正则表达式reg = /(\d{3}(?=\d))/进行匹配。
刚开始看这个表达式,也是有些疑惑的,表达式的前半部分(\d{3})很好理解,就是匹配3个数字,但是后半部分(?=\d) 我刚看的时候还是没看懂。后来查了一下正则表达式(?=pattern)的语法,得到如下描述

正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,”Windows(?=95|98|NT|2000)”能匹配”Windows2000”中的”Windows”,但不能匹配”Windows3.1”中的”Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

初看这个描述的时候,也是感觉云里雾里。不过结合代码中的实际列子,自己算是理解了其中的意思,请看如下列子。

//列1
var a = '13245646';
var reg = /(\d{3})(\d)/g 
a.replace(reg,'$1-$2-');
//输出
//"132-4-564-6-"

显然我们看到$1指向的是(/d{3})$2指向的是(\d)
我们在看看使用?= 的效果

//列2
var a = '13245646';
var reg = /(\d{3})(?=\d)/g 
a.replace(reg,'$1-$2-');
//输出
//"132-$2-456-$2-46"

可以看到$1 还是和之前一样,但是$2 却发生了变化,它不在指代某一个分组,而是单纯的文字了。这是因为在我们这个表达式中只有分组一(\d{3}) 是生效的,而没有其他分组,我们来验证一下

//列3
var a = '13245646';
var reg = /(\d{3})(?=\d)(\d)/g 
a.replace(reg,'$1-$2-');
//输出
//"132-4-564-6-"

发现没有!!!这个结果和我们第一个列子的结果是一模一样的,那么文章开头看到的解释中的这部分话就很好理解了

这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用

同样,通过这三个列子的结果,我们也可以理解下面这句话了

预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
我们再来对比一下列1和列2

var a = '13245646';
//1
var reg1 = /(\d{3})(\d)/g
var reg2 = /(\d{3})(?=\d)/g
console.log('reg1:', a.match(reg1) )
console.log('reg2:',a.match(reg2) )
//输出
//reg1: (2) ["1324", "5646"]
//reg2: (2) ["132", "456"]

可以看到reg1在下一次的匹配中,是从(\d)之后的下一个字符开始匹配,而reg2中的下一次匹配时,却是直接从(\d{3})的下一个字符开始匹配。

所以这就解释了上面的那段话了。

好了,不多说废话了,给出具体的解决方法吧。show me the code .

function reverseStr(str){
    return str.split('').reverse().join('');
}
function replace3Int(str){
    return str.replace(/(\d{3})(?=\d)/g, '$1,')
}

function  currency (intStr) {
    return  reverseStr(replace3Int(reverseStr(intStr) ))
}

var a = '12345678';
currency(a);
// "12,345,678"

以上方法给出了如何对整数部分进行千分位,结合小数部分的自行处理即可。

我在网上也看到了另外一种很巧妙的方法来实现,使用的是number.toLocaleString方法
但是这个方法有一点需要注意:那就是小数部分的一定要单独处理
example

var a = 123456789;
a.toLocaleString(); //"123,456,789"
var b = 14654651156.21345
b.toLocaleString(); //"14,654,651,156.213"

有没有发现,小数部分被直接截取了3位,所以小数部分还是需要单独处理一下的。

Logo

前往低代码交流专区

更多推荐