返回信息流如题,在传递long类型id时最后几位给我丢失了。想请教下除了在后端将long指定使用string的序列化器以外,可以在前端用js解决这个问题吗
这是一条镜像帖。来源:北邮人论坛 / java-script / #6109同步于 2022/3/1
该镜像源已超过 30 天没有更新,可能在源站已被删除。
JavaScript机器人发帖
请教下js如何接受,发送long型参数
a49781178
2022/3/1镜像同步11 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
所以前端有办法解决这个问题吗?还是只能够后端传string
【 在 superheart (BobLee) 的大作中提到: 】
: js语言特性,js用number接收后端传的long,number的范围时(-2^53,2^53),long的范围是(-2^64,2^64-1)
用 String 吧,js 的数据类型挺多坑的。
【 在 a49781178 的大作中提到: 】
: 所以前端有办法解决这个问题吗?还是只能够后端传string
就如果前端用string,后端用long,然后不做处理的可行吗?
【 在 LeeSir (【意涵团】弈晨) 的大作中提到: 】
: 用 String 吧,js 的数据类型挺多坑的。
【 在 a49781178 的大作中提到: 】
: 就如果前端用string,后端用long,然后不做处理的可行吗?
不建议这么做,因为后端接口未必只有这一个地方在用,你还要每个地方都要改一遍吗?而且,js是弱类型语言,后端传的long,前端自动转成number了,你怎么用string接受?
get√,多谢指点
【 在 superheart (BobLee) 的大作中提到: 】
: 不建议这么做,因为后端接口未必只有这一个地方在用,你还要每个地方都要改一遍吗?而且,js是弱类型语言,后端传的long,前端自动转成number了,你怎么用string接受?
JavaScript的Number类型其实就是IEEE 754,对应到C就是double,准确而言是64bit的浮点数。如果想支持到能够容纳long表示范围的数值,可以用BigInt,但有几个限制:
1. 没有默认的toJSON接口实现,不过可以简单的使用BigInt.prototype.toJSON = function() { return this.toString() }来实现(就是将其序列化为字符串)
2. 有浏览器兼容问题,不过这个影响不大,因为是19年的提案,只要不碰IE现在应该都能用:https://caniuse.com/bigint
3. 无法直接与Number类型数值做计算,且无法享受到常见JavaScript引擎对于整数字面量数值或JIT后代码的优化(主要指的是speculative optimizations)。总的来说是会比被优化为32bit的Number类型要慢的。当然,肯定要比早期没有BigInt时期在用户态使用字符串模拟的方案快很多。至少据我所知,目前V8对于BigInt的数值计算和JIT是没有什么特别的待遇的,尽管在实现初期的博客里就提到过可以对BigInt-64做特殊处理。但不管怎样,总归是tagged,快是不可能快的。
另外,如果你想用BigInt完全模拟C的long(或者,64bit整型)的话,可以再包一层BigInt.asIntN(64, bigIntValue)方法调用。
再说序列化。我姑且假设你提到的序列化指的是JSON。那么从我能理解的最浅显的JSON spec(https://www.json.org/json-en.html)来看(我只看了McKeeman Form),JSON并没有规定里面的number类型必须是IEEE 754,或者说JavaScript的Number。这里把JSON中number相关的McKeeman Form复制过来:
number
integer fraction exponent
integer
digit
onenine digits
'-' digit
'-' onenine digits
digits
digit
digit digits
digit
'0'
onenine
onenine
'1' . '9'
fraction
""
'.' digits
exponent
""
'E' sign digits
'e' sign digits
sign
""
'+'
'-'
可见和IEEE 754没啥关系。那么很明显,前后端确实可以去定义能够序列化和反序列化BigInt/long类型的函数。只不过其字面量形式应该是JSON里面的number,是JSON里面的string,还是JavaScript里面的BigInt字面量(就是Number字面量后面加个"n",比如1234567890n),甚至自定义一套,孰优孰劣就改由自己去探索了。
如果你说的序列化方式是protobuf这样的非自包含协议(与自包含的JSON相对应,protobuf需要IDL才能序列和反序列化),那么早就有人提供解决方案了:https://github.com/protobufjs/protobuf.js就使用了long.js来解决long的序列化反序列化问题。
如果你是想研究原理,深挖深挖,那么请研究相关 IEEE 标准和 ECMAscript 的发展。
如果你只是工程实践上要解决问题,作为一个工作了 10+年 的前端,可以明确告诉你,在数据交给前端之前转成 string,前端就当成 string 处理。