千位分隔符的思考
英语里没有
万
亿
,只有百万(million)
十亿(billion)
,千位分隔符就是这么产生的
1, 000 one thousand 一千
1, 000, 000 one million 一百万
1, 000, 000, 000 one billion 十亿
方案一: 正则
思路: 从个位往左数起,每三位前插入一个千位分隔符 ,
,排除最开始的位置
String(Number).replace(/(\d)(?=(\d{3})+$)/g, "$1,");
String(1234567890).replace(/(\d)(?=(\d{3})+$)/g, "$1,");
// "1,234,567,890"
说明:
g
是表示全局匹配的修饰符,全局匹配指查找所有匹配而非在找到第一个匹配后停止。$
是表示结尾的量词,如n$
,匹配的是任何以n
为结尾的字符串。\d
是查找数字的元字符。n{X}
是匹配包含 X 个 n 的序列的字符串的量词。+
匹配前面的子表达式一次或多次;*
匹配前面的子表达式0次或多次。?
匹配前面的子表达式0次或1次,或指明一个非贪婪限定符。x(?=y)
先行断言,匹配'x'仅仅当'x'后面跟着'y'match()
String对象的方法,作用是找到一个或多个正则表达式的匹配。replace()
String对象的方法,作用是替换与正则表达式匹配的子串。\B
是表示匹配非单词边界的元字符,与其互为补集的元字符是\b
,表示匹配单词边界。
方案二: toLocaleString
toLocaleString()
方法返回一个该对象的字符串表示
覆盖 toLocaleString
的对象: Array: Array.prototype.toLocaleString()
Number: Number.prototype.toLocaleString()
Date: Date.prototype.toLocaleString()
Array.prototype.toLocaleString
概述: toLocaleString()
返回一个字符串 表示数组中的元素。数组中的元素将使用各自的 toLocaleString 方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 ", ")隔开。 语法: arr.toLocaleString([locales[,options]])
参数: locales
(可选) 参数用于指定格式化对象时使用的语言环境,默认为当前环境的语言, 一般而言使用 en 或 zh 即可应付绝大多数情况。 MDN : 带有BCP47语言标记的 字符串或字符串数组
,关于locales参数的形式与解释,请看Intl页面 options
(可选) 一个可配置属性的 对象
[1, 2, 3, 4].toLocaleString()
// "1,2,3,4"
var prices = ['¥7', 500, 8123, 12];
prices.toLocaleString('ja-JP', {
style: 'currency',
currency: 'JPY'
});
// "¥7,¥500,¥8,123,¥12"
至此, 将数组的 toLocaleString
方法理解为, 对数组每一项应用相应的 toLocaleString
方式, 然后返回组合的字符串, 即可.
Number.prototype.toLocaleString
其实不用传任何参数的时候, 千位分隔符的问题似乎就已经解决了.
const number = 123456789;
number.toLocaleString(); // 123,456,789
//对于中文场景下,toLocaleString('en-US')中的'en-US'理论上是可以缺省的,
//也就是直接(123456789).toLocaleString()也是可以得到123,456,789。
//但是如果你的产品可能海外用户使用,则保险起见,还是保留'en-US'。
如果传参数的时候, 是什么样子呢 ? ( 以下主要针对 options
参数, locales
参数一般使用 zh
.) style
表示格式化时使用的样式,默认值是 decimal
也就是纯数字,也可为 percent
百分比显示与 currency
货币显示。值为 currency
时必须同时指定 options
中的 currency
属性,否则报错。
const number = 2333333;
number.toLocaleString('zh', {
style: 'decimal'
}); //2,333,333
number.toLocaleString('zh', {
style: 'percent'
}); //233,333,300%
number.toLocaleString('zh', {
style: 'currency'
});
//Uncaught TypeError: Currency code is required with currency style.
接下来的两个属性是 style
设为 currency
时才有用的,它们分别是 currency
与 currencyDisplay
,前者指定对应的货币,如 USD
、 EUR
与 CNY
等,不区分大小写。后者是货币符号的展示样式,默认值是 symbol
,即对应的符号,如 CNY
是 ¥
。该属性的值也可以是 code
与 name
const number = 2333333;
number.toLocaleString('zh', {
style: 'currency',
currency: 'CNY'
});
//¥2,333,333.00
number.toLocaleString('zh', {
style: 'currency',
currency: 'cny',
currencyDisplay: 'code'
});
//CNY2,333,333.00
number.toLocaleString('zh', {
style: 'currency',
currency: 'cny',
currencyDisplay: 'name'
});
//2,333,333.00人民币
最后是两组相当强大的属性,某些场景下能带来极大的便利。第一组是 minimumIntegerDigits
、 minimumFractionDigits
与 maximumFractionDigits
,用于指定整数至少位数 与 小数的至少和至多位数,不够则用0去凑。简单说,自动补0!
let number = 2333.3;
//整数至少5位
number.toLocaleString('zh', {
minimumIntegerDigits: 5
}); //02,333.3
//如果不想有分隔符,可以指定useGrouping为false
number.toLocaleString('zh', {
minimumIntegerDigits: 5,
useGrouping: false
});
//02333.3
//小数至少2位
number.toLocaleString('zh', {
minimumFractionDigits: 2,
useGrouping: false
}); //2333.30
//小数至多2位
number = 666.666
number.toLocaleString('zh', {
maximumFractionDigits: 2,
useGrouping: false
}); //666.67
拓展:
ES2017
引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()
用于头部补全,padEnd()
用于尾部补全。详情戳阮一峰大大.
另一组是 minimumSignificantDigits
与 maximumSignificantDigits
,用于控制 有效数字 位数,只要设置了这一组属性,第一组属性全部忽略不算
const number = 1234.5;
number.toLocaleString('zh', {
minimumSignificantDigits: 7,
useGrouping: false
}); //1234.500
number.toLocaleString('zh', {
maximumSignificantDigits: 4,
useGrouping: false
}); //1235
Date.prototype.toLocaleString
直接进入到 options
参数的讲解: hour12
表示是使用十二小时制还是二十四小时制,默认值视 locales
而定
const date = new Date();
date.toLocaleString('zh', {
hour12: true
}); //"2018/5/9 下午3:20:07"
date.toLocaleString('zh', {
hour12: false
}); //"2018/5/9 15:20:07"
date.toLocaleString('en', {
hour12: true
}); //"5/9/2018, 3:20:07 PM"
date.toLocaleString('en', {
hour12: false
}); //"5/9/2018, 15:20:07"
下面介绍其他属性 : weekday
、 era
(时代)、 year
、 month
、 day
、 hour
、 minute
、 second
timeZoneName
weekday
与 era
可选值: narrow
、 short
、 long
const date = new Date();
date.toLocaleString('en', {
weekday: 'narrow',
era: 'narrow'
}); //W A
date.toLocaleString('en', {
weekday: 'short',
era: 'short'
}); //Wed AD
date.toLocaleString('en', {
weekday: 'long',
era: 'long'
}); //Wednesday Anno Domini
timeZoneName
可选值 short
、 long
const date = new Date();
date.toLocaleString('zh', {
timeZoneName: 'short'
}); // "2018/5/9 GMT+8 下午3:29:47"
date.toLocaleString('zh', {
timeZoneName: 'long'
}); // "2018/5/9 中国标准时间 下午3:29:47"
剩下的属性,均可以取值为 numeric
与 2-digit
,简单说就是否仅用两位数字表示
const date = new Date();
date.toLocaleString('zh', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
}); //"2018/5/9 下午3:32:15"
date.toLocaleString('zh', {
year: '2-digit',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
}); //"18/05/09 下午3:32:15"
//比较奇怪的是 hour、minute 与 second 三个属性,无论设置为何值,表现都是一样的??
month
属性, 除去 numeric
与 2-digit
外,它额外多三个属性,分别是 narrow
、 short
与 long
const date = new Date();
date.toLocaleString('zh', {
month: 'long'
}); // "五月"
date.toLocaleString('zh', {
month: 'short'
}); // "5月"
date.toLocaleString('zh', {
month: 'narrow'
}); // "5"