前言
今天在學(xué)習(xí)kotlin項(xiàng)目時(shí),發(fā)現(xiàn)項(xiàng)目中有一個(gè)奇怪的現(xiàn)象。凡是,將ID返回給前端時(shí),都是以String的類型返回,而不是常見(jiàn)的整形。
將代碼研究了很久,不理解這種奇怪的行為,為什么不直接以數(shù)字類型傳給前端呢?Kotlin小伙伴,告訴我較大數(shù)字會(huì)在JavaScript的JSON轉(zhuǎn)換時(shí),丟失精度。
問(wèn)題
當(dāng)使用Long類型以JSON格式傳給前端時(shí),數(shù)字會(huì)變得不一致(丟失精度)。
// 后端返回的原始數(shù)據(jù)
{
"id": 113145644503269376
}
// 前端解析到的數(shù)據(jù)
{
"id": 113145644503269380
}
神奇的事情發(fā)生了,id發(fā)生了變化。
原因
在JavaScript中,Number類型有最大和最小的安全整數(shù)。
范圍如下:
// ES6
Number.MIN_SAFE_INTEGER; // -9007199254740991
Number.MAX_SAFE_INTEGER; // 9007199254740991
在解析序列化的JSON時(shí),如果JSON解析器將它們強(qiáng)制轉(zhuǎn)換為Number類型,那么超出此范圍的整數(shù)值可能會(huì)被破壞。在工作中使用
String類型代替,是一個(gè)可行的解決方案。
我們做兩個(gè)實(shí)驗(yàn)
// 例子一
Number(9007199254740999) // 9007199254741000 超過(guò)最大安全整數(shù),轉(zhuǎn)換時(shí),精度丟失。
// 例子二
var x = 9007199254740992;
var y = -x;
x == x + 1; // true
y == y - 1; // true
解決辦法
將較大數(shù)字類型的ID,以String類型傳遞給前端。
總結(jié)
在kotlin項(xiàng)目中,ID是使用ID生成器生成的18位整數(shù),但是JavaScript中Number最大的安全整數(shù)為16位。生成的ID超過(guò)了最大安全數(shù),故在JSON解析時(shí),發(fā)生精度丟失。因此,推薦使用String類型來(lái)傳遞較大整數(shù)。