我想用JavaScript格式化价格。我想要一个函数,它将浮点作为参数,并返回如下格式的字符串:
"$ 2,500.00"
我该怎么做?
我想用JavaScript格式化价格。我想要一个函数,它将浮点作为参数,并返回如下格式的字符串:
"$ 2,500.00"
我该怎么做?
当前回答
YUI代码库使用以下格式:
format: function(nData, oConfig) {
oConfig = oConfig || {};
if(!YAHOO.lang.isNumber(nData)) {
nData *= 1;
}
if(YAHOO.lang.isNumber(nData)) {
var sOutput = nData + "";
var sDecimalSeparator = (oConfig.decimalSeparator) ? oConfig.decimalSeparator : ".";
var nDotIndex;
// Manage decimals
if(YAHOO.lang.isNumber(oConfig.decimalPlaces)) {
// Round to the correct decimal place
var nDecimalPlaces = oConfig.decimalPlaces;
var nDecimal = Math.pow(10, nDecimalPlaces);
sOutput = Math.round(nData*nDecimal)/nDecimal + "";
nDotIndex = sOutput.lastIndexOf(".");
if(nDecimalPlaces > 0) {
// Add the decimal separator
if(nDotIndex < 0) {
sOutput += sDecimalSeparator;
nDotIndex = sOutput.length-1;
}
// Replace the "."
else if(sDecimalSeparator !== "."){
sOutput = sOutput.replace(".",sDecimalSeparator);
}
// Add missing zeros
while((sOutput.length - 1 - nDotIndex) < nDecimalPlaces) {
sOutput += "0";
}
}
}
// Add the thousands separator
if(oConfig.thousandsSeparator) {
var sThousandsSeparator = oConfig.thousandsSeparator;
nDotIndex = sOutput.lastIndexOf(sDecimalSeparator);
nDotIndex = (nDotIndex > -1) ? nDotIndex : sOutput.length;
var sNewOutput = sOutput.substring(nDotIndex);
var nCount = -1;
for (var i=nDotIndex; i>0; i--) {
nCount++;
if ((nCount%3 === 0) && (i !== nDotIndex)) {
sNewOutput = sThousandsSeparator + sNewOutput;
}
sNewOutput = sOutput.charAt(i-1) + sNewOutput;
}
sOutput = sNewOutput;
}
// Prepend prefix
sOutput = (oConfig.prefix) ? oConfig.prefix + sOutput : sOutput;
// Append suffix
sOutput = (oConfig.suffix) ? sOutput + oConfig.suffix : sOutput;
return sOutput;
}
// Still not a number. Just return it unaltered
else {
return nData;
}
}
它需要编辑,因为YUI库是可配置的,比如用“.”替换oConfig.decimalSeparator。
其他回答
快速快捷的解决方案(适用于任何地方!)
(12345.67).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,'); // 12,345.67
此解决方案背后的思想是用第一个匹配和逗号替换匹配的部分,即“$&,”。匹配是使用前瞻方法完成的。您可以将表达式读为“匹配一个数字,如果它后面跟着三个数字集(一个或多个)和一个点的序列”。
测验:
1 --> "1.00"
12 --> "12.00"
123 --> "123.00"
1234 --> "1,234.00"
12345 --> "12,345.00"
123456 --> "123,456.00"
1234567 --> "1,234,567.00"
12345.67 --> "12,345.67"
演示:http://jsfiddle.net/hAfMM/9571/
扩展短解决方案
您还可以扩展Number对象的原型,以添加对任意数量的小数[0..n]和数字组大小[0..x]的额外支持:
/**
* Number.prototype.format(n, x)
*
* @param integer n: length of decimal
* @param integer x: length of sections
*/
Number.prototype.format = function(n, x) {
var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')';
return this.toFixed(Math.max(0, ~~n)).replace(new RegExp(re, 'g'), '$&,');
};
1234..format(); // "1,234"
12345..format(2); // "12,345.00"
123456.7.format(3, 2); // "12,34,56.700"
123456.789.format(2, 4); // "12,3456.79"
演示/测试:http://jsfiddle.net/hAfMM/435/
超扩展短解决方案
在此超级扩展版本中,您可以设置不同的分隔符类型:
/**
* Number.prototype.format(n, x, s, c)
*
* @param integer n: length of decimal
* @param integer x: length of whole part
* @param mixed s: sections delimiter
* @param mixed c: decimal delimiter
*/
Number.prototype.format = function(n, x, s, c) {
var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
num = this.toFixed(Math.max(0, ~~n));
return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
};
12345678.9.format(2, 3, '.', ','); // "12.345.678,90"
123456.789.format(4, 4, ' ', ':'); // "12 3456:7890"
12345678.9.format(0, 3, '-'); // "12-345-679"
演示/测试:http://jsfiddle.net/hAfMM/612/
通常,有多种方法可以执行相同的操作,但我会避免使用Number.prototype.toLocaleString,因为它可以根据用户设置返回不同的值。
我也不建议扩展Number.prototype-扩展原生对象原型是一种糟糕的做法,因为它可能会与其他人的代码(例如库/框架/插件)发生冲突,并且可能与未来的JavaScript实现/版本不兼容。
我认为正则表达式是解决这个问题的最佳方法,下面是我的实现:
/**
* Converts number into currency format
* @param {number} number Number that should be converted.
* @param {string} [decimalSeparator] Decimal separator, defaults to '.'.
* @param {string} [thousandsSeparator] Thousands separator, defaults to ','.
* @param {int} [nDecimalDigits] Number of decimal digits, defaults to `2`.
* @return {string} Formatted string (e.g. numberToCurrency(12345.67) returns '12,345.67')
*/
function numberToCurrency(number, decimalSeparator, thousandsSeparator, nDecimalDigits){
//default values
decimalSeparator = decimalSeparator || '.';
thousandsSeparator = thousandsSeparator || ',';
nDecimalDigits = nDecimalDigits == null? 2 : nDecimalDigits;
var fixed = number.toFixed(nDecimalDigits), //limit/add decimal digits
parts = new RegExp('^(-?\\d{1,3})((?:\\d{3})+)(\\.(\\d{'+ nDecimalDigits +'}))?$').exec( fixed ); //separate begin [$1], middle [$2] and decimal digits [$4]
if(parts){ //number >= 1000 || number <= -1000
return parts[1] + parts[2].replace(/\d{3}/g, thousandsSeparator + '$&') + (parts[4] ? decimalSeparator + parts[4] : '');
}else{
return fixed.replace('.', decimalSeparator);
}
}
JavaScript中有一个内置函数toFixed:
var num = new Number(349);
document.write("$" + num.toFixed(2));
处理货币输出(包括负数)的函数。样本输出:$5.23-$5.23
function formatCurrency(total) {
var neg = false;
if(total < 0) {
neg = true;
total = Math.abs(total);
}
return (neg ? "-$" : '$') + parseFloat(total, 10).toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1,").toString();
}
String.prototype.toPrice = function () {
var v;
if (/^\d+(,\d+)$/.test(this))
v = this.replace(/,/, '.');
else if (/^\d+((,\d{3})*(\.\d+)?)?$/.test(this))
v = this.replace(/,/g, "");
else if (/^\d+((.\d{3})*(,\d+)?)?$/.test(this))
v = this.replace(/\./g, "").replace(/,/, ".");
var x = parseFloat(v).toFixed(2).toString().split("."),
x1 = x[0],
x2 = ((x.length == 2) ? "." + x[1] : ".00"),
exp = /^([0-9]+)(\d{3})/;
while (exp.test(x1))
x1 = x1.replace(exp, "$1" + "," + "$2");
return x1 + x2;
}
alert("123123".toPrice()); //123,123.00
alert("123123,316".toPrice()); //123,123.32
alert("12,312,313.33213".toPrice()); //12,312,313.33
alert("123.312.321,32132".toPrice()); //123,312,321.32