我想用JavaScript格式化价格。我想要一个函数,它将浮点作为参数,并返回如下格式的字符串:
"$ 2,500.00"
我该怎么做?
我想用JavaScript格式化价格。我想要一个函数,它将浮点作为参数,并返回如下格式的字符串:
"$ 2,500.00"
我该怎么做?
当前回答
适用于所有当前浏览器
使用toLocaleString以货币的语言敏感表示形式格式化货币(使用ISO 4217货币代码)。
(2500).toLocaleString("en-GB", {style: "currency", currency: "GBP", minimumFractionDigits: 2})
avenmore的南非兰特代码片段示例:
console.log((2500).toLocaleString(“en-ZA”,{style:“currency”,currency:“ZAR”,minimumFractionDigits:2}))//->2 500,00兰特console.log((2500).toLocaleString(“en-GB”,{style:“currency”,currency:“ZAR”,minimumFractionDigits:2}))//->2500欧元
其他回答
这里有一个普通JavaScript的简单格式化程序:
function numberFormatter (num) {
console.log(num)
var wholeAndDecimal = String(num.toFixed(2)).split(".");
console.log(wholeAndDecimal)
var reversedWholeNumber = Array.from(wholeAndDecimal[0]).reverse();
var formattedOutput = [];
reversedWholeNumber.forEach( (digit, index) => {
formattedOutput.push(digit);
if ((index + 1) % 3 === 0 && index < reversedWholeNumber.length - 1) {
formattedOutput.push(",");
}
})
formattedOutput = formattedOutput.reverse().join('') + "." + wholeAndDecimal[1];
return formattedOutput;
}
这里有一些解决方案,都通过了测试套件。包括测试套件和基准测试。如果你想复制和粘贴来测试,试试这个要点。
方法0(RegExp)
它是基于VisioN的答案,但如果没有小数点,它会修复。
if (typeof Number.prototype.format === 'undefined') {
Number.prototype.format = function (precision) {
if (!isFinite(this)) {
return this.toString();
}
var a = this.toFixed(precision).split('.');
a[0] = a[0].replace(/\d(?=(\d{3})+$)/g, '$&,');
return a.join('.');
}
}
方法1
if (typeof Number.prototype.format === 'undefined') {
Number.prototype.format = function (precision) {
if (!isFinite(this)) {
return this.toString();
}
var a = this.toFixed(precision).split('.'),
// Skip the '-' sign
head = Number(this < 0);
// Skip the digits that's before the first thousands separator
head += (a[0].length - head) % 3 || 3;
a[0] = a[0].slice(0, head) + a[0].slice(head).replace(/\d{3}/g, ',$&');
return a.join('.');
};
}
方法2(拆分到阵列)
if (typeof Number.prototype.format === 'undefined') {
Number.prototype.format = function (precision) {
if (!isFinite(this)) {
return this.toString();
}
var a = this.toFixed(precision).split('.');
a[0] = a[0]
.split('').reverse().join('')
.replace(/\d{3}(?=\d)/g, '$&,')
.split('').reverse().join('');
return a.join('.');
};
}
方法3(循环)
if (typeof Number.prototype.format === 'undefined') {
Number.prototype.format = function (precision) {
if (!isFinite(this)) {
return this.toString();
}
var a = this.toFixed(precision).split('');
a.push('.');
var i = a.indexOf('.') - 3;
while (i > 0 && a[i-1] !== '-') {
a.splice(i, 0, ',');
i -= 3;
}
a.pop();
return a.join('');
};
}
用法示例
console.log('======== Demo ========')
console.log(
(1234567).format(0),
(1234.56).format(2),
(-1234.56).format(0)
);
var n = 0;
for (var i=1; i<20; i++) {
n = (n * 10) + (i % 10)/100;
console.log(n.format(2), (-n).format(2));
}
分离器
如果我们需要自定义千位分隔符或小数分隔符,请使用replace():
123456.78.format(2).replace(',', ' ').replace('.', ' ');
测试套件
function assertEqual(a, b) {
if (a !== b) {
throw a + ' !== ' + b;
}
}
function test(format_function) {
console.log(format_function);
assertEqual('NaN', format_function.call(NaN, 0))
assertEqual('Infinity', format_function.call(Infinity, 0))
assertEqual('-Infinity', format_function.call(-Infinity, 0))
assertEqual('0', format_function.call(0, 0))
assertEqual('0.00', format_function.call(0, 2))
assertEqual('1', format_function.call(1, 0))
assertEqual('-1', format_function.call(-1, 0))
// Decimal padding
assertEqual('1.00', format_function.call(1, 2))
assertEqual('-1.00', format_function.call(-1, 2))
// Decimal rounding
assertEqual('0.12', format_function.call(0.123456, 2))
assertEqual('0.1235', format_function.call(0.123456, 4))
assertEqual('-0.12', format_function.call(-0.123456, 2))
assertEqual('-0.1235', format_function.call(-0.123456, 4))
// Thousands separator
assertEqual('1,234', format_function.call(1234.123456, 0))
assertEqual('12,345', format_function.call(12345.123456, 0))
assertEqual('123,456', format_function.call(123456.123456, 0))
assertEqual('1,234,567', format_function.call(1234567.123456, 0))
assertEqual('12,345,678', format_function.call(12345678.123456, 0))
assertEqual('123,456,789', format_function.call(123456789.123456, 0))
assertEqual('-1,234', format_function.call(-1234.123456, 0))
assertEqual('-12,345', format_function.call(-12345.123456, 0))
assertEqual('-123,456', format_function.call(-123456.123456, 0))
assertEqual('-1,234,567', format_function.call(-1234567.123456, 0))
assertEqual('-12,345,678', format_function.call(-12345678.123456, 0))
assertEqual('-123,456,789', format_function.call(-123456789.123456, 0))
// Thousands separator and decimal
assertEqual('1,234.12', format_function.call(1234.123456, 2))
assertEqual('12,345.12', format_function.call(12345.123456, 2))
assertEqual('123,456.12', format_function.call(123456.123456, 2))
assertEqual('1,234,567.12', format_function.call(1234567.123456, 2))
assertEqual('12,345,678.12', format_function.call(12345678.123456, 2))
assertEqual('123,456,789.12', format_function.call(123456789.123456, 2))
assertEqual('-1,234.12', format_function.call(-1234.123456, 2))
assertEqual('-12,345.12', format_function.call(-12345.123456, 2))
assertEqual('-123,456.12', format_function.call(-123456.123456, 2))
assertEqual('-1,234,567.12', format_function.call(-1234567.123456, 2))
assertEqual('-12,345,678.12', format_function.call(-12345678.123456, 2))
assertEqual('-123,456,789.12', format_function.call(-123456789.123456, 2))
}
console.log('======== Testing ========');
test(Number.prototype.format);
test(Number.prototype.format1);
test(Number.prototype.format2);
test(Number.prototype.format3);
基准
function benchmark(f) {
var start = new Date().getTime();
f();
return new Date().getTime() - start;
}
function benchmark_format(f) {
console.log(f);
time = benchmark(function () {
for (var i = 0; i < 100000; i++) {
f.call(123456789, 0);
f.call(123456789, 2);
}
});
console.log(time.format(0) + 'ms');
}
// If not using async, the browser will stop responding while running.
// This will create a new thread to benchmark
async = [];
function next() {
setTimeout(function () {
f = async.shift();
f && f();
next();
}, 10);
}
console.log('======== Benchmark ========');
async.push(function () { benchmark_format(Number.prototype.format); });
next();
已经有好的答案了。这里有一个简单的乐趣尝试:
function currencyFormat(no) {
var ar = (+no).toFixed(2).split('.');
return [
numberFormat(ar[0] | 0),
'.',
ar[1]
].join('');
}
function numberFormat(no) {
var str = no + '';
var ar = [];
var i = str.length -1;
while(i >= 0) {
ar.push((str[i-2] || '') + (str[i-1] || '') + (str[i] || ''));
i = i-3;
}
return ar.reverse().join(',');
}
然后运行一些示例:
console.log(
currencyFormat(1),
currencyFormat(1200),
currencyFormat(123),
currencyFormat(9870000),
currencyFormat(12345),
currencyFormat(123456.232)
)
我从accounting.js中找到了这个。它非常简单,非常适合我的需要。
//默认用法:accounting.formatMoney(12345678);//$12,345,678.00//欧洲格式(自定义符号和分隔符),也可以使用options对象作为第二个参数:accounting.formatMoney(4999.99,“€”,2,“.”,“,”);//€4.999,99//负值可以很好地格式化:accounting.formatMoney(-50万,“£”,0);//£ -500,000//简单的“格式”字符串允许控制符号位置(%v=值,%s=符号):accounting.formatMoney(5318008,{符号:“GBP”,格式:“%v%s”});//5318008.00 GBP//右侧的欧元货币符号accounting.formatMoney(5318008,{符号:“€”,精度:2,千:“.”,十进制:“,”,格式:“%v%s”});//1.008,00€
数字(值).to固定(2).replace(/(\d)(?=(\d{3})+(?!\d))/g,“$1,”)