思考题 number格式化
16 May 2016

jansesun原创,转载请注明出处

之前在UESTC前端群里跟一些朋友分享了一些javascript的思考题,旨在促进群内技术讨论,共同进步。期间不乏思维的火花,一直想将这些宝贵的财富沉淀下来,以便日后翻阅。

这个问题是在我在实际工作中遇到的,将后台返回的计数转化为符合英文阅读习惯的展现方式,比如将1234567表示为'1,234,567',我当时觉得有简洁的方法,但是又一时想不出来,就把这个问题丢到群里让大家讨论,最后大家给出了四种方案,当然在实际项目中,我采用了兼容性和书写优雅的最后一种,其他几种对开阔思路还是挺有好处的,希望对大家有所启示。

方案一 toLocaleString

这是javascript的Number对象的内置方法,如果没有讨厌的IE,本应该是极好的

function num2Str(num) {
	// 兼容性问题,不可控IE下1234会变为'1,234.00'
	return num.toLocaleString();
}

方案二 截取法

这是一种最朴素的思想,先从起始位置截断,让剩余字符串的长度为3的倍数,然后每隔3位,插入逗号分隔,然后再将截取的前缀和插入逗号的剩余字符串拼接。

function num2Str(num) {
	var len, prefix, substr, index;
	num += '';
	len = num.length;
	index = len % 3;
	prefix = num.substr(0, index);
	substr = num.substr(index);
	return len > 3 ? (index === 0 ? '' : prefix + ',') + substr.replace(/(\d{3})(?=\d)/g, '$1,'): prefix;
}

方案三 补齐法

这是一种和方案二相反的思想,因为目标字符串只有数字和逗号为合法字符,所以考虑先用其他字符将字符串补齐到长度为3的倍数,然后每隔3位,插入逗号分隔,然后再将其他字符剔除即可。

function num2Str(num) {
	var len;
	num += '';
	len = num.length;
	index = len % 3;
	return ('a'.repeat(index ? 3 - index : 0) + num).replace(/(\S{3})(?=\d)/g, '$1,').replace(/a/g, '');
};

方案四 正则正向前瞻

这个方案由群里的我怎能不变态提供

这种方法巧妙的利用了正则表达式的正向前瞻,这个思想可以扩展为任意等差数列位置插入指定字符,具体的做法就请读者自己试验了。

function num2Str(num) {
	return num.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
}

方案五 零宽断言(终极方案)

这个方案由我带的实习生提供

这种方法也是利用正则表达式的正向前瞻,和方案四思路基本一致,但更加简洁。

function num2Str(num) {
	return num.replace(/(?=\B(?:\d{3})+$)/g, ',');
}