new Intl.NumberFormat 解决toFixed不四舍五入的问题

2,283 阅读2分钟

toFixed()方法的坑

1. 四舍五入并不是真正的四舍五入

chrome 上的测试结果:

1.35.toFixed(1) // 1.4 正确

1.335.toFixed(2) // 1.33 错误

1.3335.toFixed(3) // 1.333 错误

1.33335.toFixed(4) // 1.3334 正确

1.333335.toFixed(5) // 1.33333 错误

1.3333335.toFixed(6) // 1.333333 错误

IE 上的测试结果:

1.35.toFixed(1) // 1.4 正确

1.335.toFixed(2) // 1.34 正确

1.3335.toFixed(3) // 1.334 正确

1.33335.toFixed(4) // 1.3334 正确

1.333335.toFixed(5) // 1.33334 正确

1.3333335.toFixed(6) // 1.333334 正确

综上可以看到, 四舍五入在 chrome 中并不是真正的四舍五入

2. 使用 Intl.NumberFormat()构造函数格式化数据

Intl.NumberFormat是浏览器内置的一个做数字做格式化处理的 API, 它是 Intl 命名空间下的一个构造器属性, 功能异常强大 👍 参考 MDN

1.最少 & 最多保留几位小数

new Intl.NumberFormat(undefined, { minimumFractionDigits: 3, maximumFractionDigits: 3 }).format(123456.78967)
// "123,456.790"

如果你这里有严格要求,建议把minimumFractionDigitsmaximumFractionDigits都指定上, 要不可能会被舍弃掉, 比如只写maximumFractionDigits

new Intl.NumberFormat(undefined, {maximumFractionDigits: 3 }).format(123456.78967)
// "123,456.79"

// 如果把原始数据变为123456.78867
new Intl.NumberFormat(undefined, {maximumFractionDigits: 3 }).format(123456.78867)
// "123,456.789"   此时又变成了三位了

我们最常用的应该是保留两位小数

new Intl.NumberFormat(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(123456.78967)
// "123,456.79"

我们来验证一下上面使用toFixed的还有问题吗

new Intl.NumberFormat(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(1.335)
// "1.34"

new Intl.NumberFormat(undefined, { minimumFractionDigits: 3, maximumFractionDigits: 3 }).format(1.3335)
// "1.334"

完美؏؏☝ᖗ乛◡乛ᖘ☝؏؏

2.总量统计(以易于阅读的形式)--- notation在IE11不被支持,

兼容的处理方案在这里: formatjs.io/docs/polyfi…

const nums = [1234, 123456.78967, 1223562434, 1223562434454, 12235624344544165]

nums.map(num => {
    return new Intl.NumberFormat('en-US', { notation: "compact" }).format(num)
})
// ["1.2K", "123K", "1.2B", "1.2T", "12,236T"]
nums.map(num => {
    return new Intl.NumberFormat('zh-CN', { notation: "compact" }).format(num)
})
// ["1234", "12万", "12亿", "1.2万亿", "12,236万亿"]
nums.map(num => {
    return new Intl.NumberFormat('ja-JP', { notation: "compact" }).format(num)
})
// ["1234", "12万", "12億", "1.2兆", "12,236兆"]

3.百分比显示

[0.01, 1.2, 0.0123].map(num => {
    return new Intl.NumberFormat(undefined, { style: 'percent', maximumFractionDigits: 2 }).format(num) 
})
// ["1%", "120%", "1.23%"]

4.不使用千分位

  • useGrouping:是否使用分组分隔符。如千位分隔符或千/万/亿分隔符,可能的值是 true 和 false ,默认值是 true
new Intl.NumberFormat(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2, useGrouping: false }).format(123456.78967)
// "123456.79"

5.加上¥符号,表示多少钱

new Intl.NumberFormat(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2, style: 'currency', currency: 'CNY' }).format(123456.78967)
// "¥123,456.79"

结束🔚

我是南飞雁,你可以叫我飞雁,我是一名奋斗者,在实现财富自由的路上……

我喜欢分享,也喜欢思考;我有自己的人生规划和梦想;但有时也很迷茫……

我从事IT行业,研究的技术领域相对比较多而杂: PHP、MySQL、Linux、JavaScript、Node.js、NoSQL、PhotoShop、音视频处理、架构集群、网络通信、生活技巧、人生三观、做人做事读书……

我总是会在自己的公众号和掘金上写下自己的所思所想和近期要做的事,希望你关注我,我是一个奋斗者,我叫南飞雁