阅读 984

JavaScript中较大整数丢失精读问题

原文链接: www.jianshu.com

前言

今天在学习kotlin项目时,发现项目中有一个奇怪的现象。凡是,将ID返回给前端时,都是以String的类型返回,而不是常见的整形。

将代码研究了很久,不理解这种奇怪的行为,为什么不直接以数字类型传给前端呢?Kotlin小伙伴,告诉我较大数字会在JavaScript的JSON转换时,丢失精度。

问题

当使用Long类型以JSON格式传给前端时,数字会变得不一致(丢失精度)。

// 后端返回的原始数据
{
  "id": 113145644503269376
}

// 前端解析到的数据
{
   "id": 113145644503269380
}
复制代码

神奇的事情发生了,id发生了变化。

原因

在JavaScript中,Number类型有最大和最小的安全整数。 范围如下:

// ES6
Number.MIN_SAFE_INTEGER;  // -9007199254740991
Number.MAX_SAFE_INTEGER; // 9007199254740991
复制代码

在解析序列化的JSON时,如果JSON解析器将它们强制转换为Number类型,那么超出此范围的整数值可能会被破坏。在工作中使用String 类型代替,是一个可行的解决方案。

我们做两个实验

// 例子一
Number(9007199254740999)  // 9007199254741000   超过最大安全整数,转换时,精度丢失。

// 例子二
var x = 9007199254740992;
var y = -x;
x == x + 1; // true 
y == y - 1; // true
复制代码

解决办法

将较大数字类型的ID,以String类型传递给前端。

总结

在kotlin项目中,ID是使用ID生成器生成的18位整数,但是JavaScript中Number最大的安全整数为16位。生成的ID超过了最大安全数,故在JSON解析时,发生精度丢失。因此,推荐使用String类型来传递较大整数。

参考资料