大家好,我是 31 岁、依旧对技术充满好奇心的小米。
有一天晚上,我在改一个看似“非常简单”的 JavaScript Bug:
页面上明明写的是 0.1 + 0.2,结果却显示成了 0.30000000000000004。
那一刻,我突然意识到我们每天都在用的 Number,其实一点都不“简单”。
于是我决定,把 JavaScript 里的 Number,当成一个住在“数字王国”的角色,认真聊一聊它的脾气、边界、怪癖,以及它是如何从“别的类型”变成数字的。
数字王国里,没有“整数”和“小数”的区别在很多语言里,数字王国是分等级的:
int 是平民
long 是贵族
float、double 是另一套体系
但 JavaScript 不一样。在 JavaScript 的世界里,数字王国只有一个身份:Number:所有数字,都是它
不管你写的是:

它们的类型都是:

没有 int,没有 float,只有 Number。但问题也正是从这里开始的。
浮点值:Number 的“浪漫主义”1、为什么 0.1 + 0.2 不等于 0.3?
我们先来看一个“经典名场面”:

第一次看到这个结果的新手,通常会怀疑人生。但在 Number 的世界里,这其实是理所当然的。原因只有一句话:
JavaScript 的 Number 使用 IEEE 754 双精度浮点数格式
你可以把它想象成这样一个故事:一个装水的杯子故事,想象你有一个杯子,只能装 二进制的水。
0.1 是十进制世界的水
倒进二进制的杯子里,只能“近似表示”
于是:
0.1 → 一个无限循环的小数
0.2 → 也是一个无限循环的小数
杯子只能装下“接近”的水量,最后一加,就溢出了一点点误差。
2、浮点数的正确比较方式
在真实项目里,我们几乎从不直接比较浮点数是否相等。
正确姿势是:比较误差是否足够小。

这里的 Number.EPSILON,你可以把它理解为:
JavaScript 能接受的最小误差单位
值的范围:Number 也有“体力极限”再强的王国,也有疆界。Number 的世界,同样有最大值和最小值。
1、Number 能表示多大?

我们可以用一张表来理解它:

2、超出范围会发生什么?

Number 就像一个老实人:
超过能力上限 → Infinity
小到无法表示 → 直接归零
3、安全整数:你以为整数就安全了吗?
这是一个非常容易被忽略的点。

所谓“安全整数”,指的是:在这个范围内,整数可以被精确表示
超过这个范围:

数字王国的会计已经算不清账了。所以:
金额
计数
ID
千万不要随便依赖超大整数的精度
NaN:数字王国里的“失踪人口”如果说 Infinity 是“力量失控”,那 NaN 就是“逻辑失踪”。
1、什么是 NaN?
NaN 的全名是:Not a Number
但它的类型却是:

是不是有点反直觉?
2、NaN 从哪里来?
你可以理解为:数字王国拒绝回答的问题
3、NaN 的最大怪癖:它不等于自己

在整个 JavaScript 世界里,只有 NaN 会否认自己。
正确判断方式只有一个:

注意区分:

NaN 常见行为总结表

NaN 一旦出现,就像“病毒”,会在计算中一路传播。
数值转换:Number 的“变形术”在 JavaScript 里,Number 最大的能力之一是:它可以从“别的类型”变成数字,但不同方式,性格完全不同。
1、Number():最正统的方式
它遵循的是整体必须是一个合法数字。
2、parseInt / parseFloat:更像“街头翻译官”

特点是:
从左到右解析
遇到非数字就停
3、隐式转换:最容易踩坑的魔法

原因只有一个:+ 既是加法,也是字符串拼接
4、数值转换方式对比表

回到最开始那个 0.1 + 0.2 的问题。那不是 JavaScript 不靠谱,而是 Number 从一开始就没承诺过“完美精度”。
Number 就像一个能力很强、但性格真实、有边界、有怪癖的老朋友。
你越了解它:
浮点误差
安全整数
NaN 行为
转换规则
你就越不会在深夜 Debug 时怀疑人生。
END如果你觉得这篇文章对你理解 Number 有帮助,欢迎点赞、转发,让更多人认识这个不简单的 Number。
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!