谨慎使用JavaScript中的toFixed方法
最近做相关报表的时候,测试小伙伴反馈导出的数据和前端页面显示的数据不对,并且经过对比发现是我的页面的数据进位有问题。之前接手项目的时候这个逻辑不是我维护的,结果排查了一下代码之后,发现了一个很有趣的问题,这里记录一下。
PS:其实这也是前端开发一个老生常谈的问题了,高手可以直接跳过啦。
问题再现
直接在在浏览器里运行如下代码:
发现了问题了没?这并不是一个标准的四舍五入。
PS:上述在代码在IE、FireFox、Chrome下运行结果还可能不一致。
银行家舍入算法?
看了不少文档说,JavaScript的文档使用的是银行家舍入算法,我感觉这篇文章《银行家舍入法 - 简书》写的比较好。
简单来说就是:
四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。
但如果你仔细求证会发现Chrome中并不一定都符合这个算法。
ECMA规范
具体我们还是来看ECMA的规范吧:《ECMAScript 2015 Language Specification – ECMA-262 6th Edition》
具体算法如下:
中文版
「修复」toFixed
查了一下项目中之前有不少地方都是使用的toFixed
方法,后续开发使用的lodash的round
方法已经避免了这个问题。当然可以使用round
方法来替换toFixed
方法,但工作量比较大,比较直接的方法直接重写toFixed
方法。
Number.prototype.toFixed = function(decimals) {
return Math.round(this * Math.pow(10, decimals)) / (Math.pow(10, decimals));
};