我想用 JavaScript 格式化价格。我想要一个将 afloat
作为参数并返回string
格式如下的函数:
"$ 2,500.00"
做到这一点的最佳方法是什么?
我想用 JavaScript 格式化价格。我想要一个将 afloat
作为参数并返回string
格式如下的函数:
"$ 2,500.00"
做到这一点的最佳方法是什么?
JavaScript 有一个数字格式化程序(国际化 API 的一部分)。
// Create our number formatter.
var formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
// These options are needed to round to whole numbers if that's what you want.
//minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
//maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
});
formatter.format(2500); /* $2,500.00 */
使用undefined
在适当位置的第一个参数(的'en-US'
中的例子)使用系统区域(在情况下,代码在浏览器中运行的用户环境)。语言环境代码的进一步解释。
这是货币代码列表。
最后一点,将其与较旧的 . toLocaleString
. 它们都提供基本相同的功能。然而, toLocaleString 在其较旧的化身(pre-Intl)中实际上并不支持语言环境:它使用系统语言环境。因此,在调试旧浏览器时,请确保您使用的是正确版本(MDN 建议检查是否存在Intl
)。如果您不关心旧浏览器或仅使用shim ,则完全无需担心这一点。
此外,对于单个项目,两者的性能相同,但如果您要格式化大量数字,则使用Intl.NumberFormat
速度会快 70 倍。因此,通常最好在Intl.NumberFormat
每次页面加载时仅使用和实例化一次。无论如何,这是等效的用法toLocaleString
:
(2500).toLocaleString('en-US', {
style: 'currency',
currency: 'USD',
}); /* $2,500.00 */
en-US
开箱即用。一种解决方案是安装full-icu,请参阅此处了解更多信息此解决方案与每个主要浏览器兼容:
const profits = 2489.8237;
profits.toFixed(3) // Returns 2489.824 (rounds up)
profits.toFixed(2) // Returns 2489.82
profits.toFixed(7) // Returns 2489.8237000 (pads the decimals)
您只需要添加货币符号(例如"$" + profits.toFixed(2)
),您的金额就会以美元为单位。
如果你需要,
在每个数字之间使用,你可以使用这个函数:
function formatMoney(number, decPlaces, decSep, thouSep) {
decPlaces = isNaN(decPlaces = Math.abs(decPlaces)) ? 2 : decPlaces,
decSep = typeof decSep === "undefined" ? "." : decSep;
thouSep = typeof thouSep === "undefined" ? "," : thouSep;
var sign = number < 0 ? "-" : "";
var i = String(parseInt(number = Math.abs(Number(number) || 0).toFixed(decPlaces)));
var j = (j = i.length) > 3 ? j % 3 : 0;
return sign +
(j ? i.substr(0, j) + thouSep : "") +
i.substr(j).replace(/(\decSep{3})(?=\decSep)/g, "$1" + thouSep) +
(decPlaces ? decSep + Math.abs(number - i).toFixed(decPlaces).slice(2) : "");
}
document.getElementById("b").addEventListener("click", event => {
document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});
<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>
像这样使用它:
(123456789.12345).formatMoney(2, ".", ",");
如果您总是要使用 '.' 和 ',' ,您可以将它们从方法调用中删除,该方法将为您默认它们。
(123456789.12345).formatMoney(2);
如果您的文化翻转了两个符号(即欧洲人)并且您想使用默认值,只需在formatMoney
方法中粘贴以下两行:
d = d == undefined ? "," : d,
t = t == undefined ? "." : t,
如果您可以使用现代 ECMAScript 语法(即通过 Babel),您可以使用这个更简单的函数:
function formatMoney(amount, decimalCount = 2, decimal = ".", thousands = ",") {
try {
decimalCount = Math.abs(decimalCount);
decimalCount = isNaN(decimalCount) ? 2 : decimalCount;
const negativeSign = amount < 0 ? "-" : "";
let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(decimalCount)).toString();
let j = (i.length > 3) ? i.length % 3 : 0;
return
negativeSign +
(j ? i.substr(0, j) + thousands : '') +
i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands) +
(decimalCount ? decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "");
} catch (e) {
console.log(e)
}
};
document.getElementById("b").addEventListener("click", event => {
document.getElementById("x").innerText = "Result was: " + formatMoney(document.getElementById("d").value);
});
<label>Insert your amount: <input id="d" type="text" placeholder="Cash amount" /></label>
<br />
<button id="b">Get Output</button>
<p id="x">(press button to get output)</p>
(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
object的原型以添加对任意数量的小数[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/
查看 JavaScript Number对象,看看它是否可以帮助您。
toLocaleString()
将使用特定于位置的千位分隔符格式化数字。toFixed()
将数字四舍五入到特定的小数位数。要同时使用这些值,必须将其类型改回数字,因为它们都输出一个字符串。
例子:
Number((someNumber).toFixed(1)).toLocaleString()
编辑
可以直接使用 toLocaleString 而不必重新转换为数字:
someNumber.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
如果您需要频繁地以类似方式格式化数字,您可以创建一个特定的对象以供重用。比如德语(瑞士):
const money = new Intl.NumberFormat('de-CH',
{ style:'currency', currency: 'CHF' });
const percent = new Intl.NumberFormat('de-CH',
{ style:'percent', maximumFractionDigits: 1, signDisplay: "always"});
可以用作:
money.format(1234.50); // output CHF 1'234.50
percent.format(0.083); // output +8.3%
很漂亮。
下面是Patrick Desjardins(别名 Daok)代码,其中添加了一些注释和一些小改动:
/*
decimal_sep: character used as decimal separator, it defaults to '.' when omitted
thousands_sep: char used as thousands separator, it defaults to ',' when omitted
*/
Number.prototype.toMoney = function(decimals, decimal_sep, thousands_sep)
{
var n = this,
c = isNaN(decimals) ? 2 : Math.abs(decimals), // If decimal is zero we must take it. It means the user does not want to show any decimal
d = decimal_sep || '.', // If no decimal separator is passed, we use the dot as default decimal separator (we MUST use a decimal separator)
/*
According to [https://stackoverflow.com/questions/411352/how-best-to-determine-if-an-argument-is-not-sent-to-the-javascript-function]
the fastest way to check for not defined parameter is to use typeof value === 'undefined'
rather than doing value === undefined.
*/
t = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, // If you don't want to use a thousands separator you can pass empty string as thousands_sep value
sign = (n < 0) ? '-' : '',
// Extracting the absolute value of the integer part of the number and converting to string
i = parseInt(n = Math.abs(n).toFixed(c)) + '',
j = ((j = i.length) > 3) ? j % 3 : 0;
return sign + (j ? i.substr(0, j) + t : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : '');
}
这里有一些测试:
// Some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert(123456789.67392.toMoney() + '\n' + 123456789.67392.toMoney(3) + '\n' + 123456789.67392.toMoney(0) + '\n' + (123456).toMoney() + '\n' + (123456).toMoney(0) + '\n' + 89.67392.toMoney() + '\n' + (89).toMoney());
// Some tests (do not forget parenthesis when using negative numbers and number with no decimals)
alert((-123456789.67392).toMoney() + '\n' + (-123456789.67392).toMoney(-3));
细微的变化是:
Math.abs(decimals)
只有在没有时才移动一点NaN
。
decimal_sep
不能再为空字符串(必须使用某种小数点分隔符)
我们typeof thousands_sep === 'undefined'
按照如何最好地确定参数是否未发送到 JavaScript 函数中的建议使用
(+n || 0)
不需要因为this
是一个Number
对象