目录
一、浮点类型计算不准确
JavaScript中的所有数据都是以64位浮点类型数据来存储的;
而学过Java都会知道对于浮点的计算需要进行特殊处理否则很难保证数据精确。
产生浮点数计算精确度不准确的的原因在于,浮点数十进制转换成二进制会变成无线不循环,而将一个无限不循环的数进行运算之后再转换为十进制得到的结果就不准确了。
解决方案:
方案一:同toFixed(num)方法来保留小数
四舍五入结果并不精确,所以并不适用于一些极端情况:
toFixed(digits) // toFixed() 精度参数须在 0 与20 之间(digits是精确的小数点后的位数)
210000 * 10000 * 1000 * 8.2 // 17219999999999.998
parseFloat(17219999999999.998.toFixed(12)); // 17219999999999.998,而正确结果为 17220000000000
对于保留小数来说还有Math.round()方法,精度不会出现问题但是仍然有个小坑,其舍入规则如下:
- 如果小数部分大于 0.5,则舍入到下一个绝对值更大的整数。
- 如果小数部分小于 0.5,则舍入到下一个绝对值更小的整数。
- 如果小数部分等于 0.5,则舍入到下一个正无穷方向上的整数。
也就是说Math(-1.5)的结果为-1。
方案二:将浮点数转换为整数运算
比如0.1 + 0.2 转换为( 1 + 2 ) / 10
同样存在问题,如下的浮点数,转换为整数之后已经超过的int的范围:
// 这两个浮点数,转化为整数之后,相乘的结果已经超过了 MAX_SAFE_INTEGER
123456.789 * 123456.789 // 转化为 (123456789 * 123456789)/1000000,结果是 15241578750.19052
方案三:将浮点数转换为字符串
需要引入一些第三方库,比如 bignumber.js,decimal.js,以及big.js等。用法类似java的大数计算。
总的来说,目前对于js的浮点计算各有缺陷,根据具体场景选择吧。
二、数组中使用名字来索引
JavaScript是不支持使用名字来多因数组的,只允许用数字下表索引。如果你使用名字作为索引,当访问数据时,JavaScript会把数组重新定义为标准对象。执行这样操作后,数组的方法及属性将不能再被使用,否则会产生错误。
let person = [];
person[0] = "John";
person[1] = "Doe";
person[2] = 46;
let x = person.length; // person.length 返回 3
let y = person[0]; // person[0] 返回 "John"
在JavaScript中,对象使用名字作为索引。
如果你使用名字作为索引,当访问数据时,JavaScript会把数组重新定义为标准对象。
执行这样操作后,数组的方法及属性将不能再使用,否则会产生错误。
let person = [];
person["firstName"] = "John";
person["lastName"] = "Doe";
person["age"] = 46;
let x = person.length; // person.length 返回 0
let y = person[0]; // person[0] 返回 undefined
因为person["firstName"]实际上是访问person的firstName属性,person数组在这时就已经被重新构造成数组了。
三、undefined与null
null用于对象,undefined用于变量,属性和方法。
对象只有被定义才有可能为null,否则为undefined。
如果需要判断一个对象是否存在,需要先判断其是否被定义,否则就会抛出错误
此贴持续更新中。。。