从零开始理解 JavaScript 中的 Number 对象:不仅仅是数字
在 JavaScript 里处理数字,其实就是在和 Number 对象打交道。无论你是在写一个简单的计数器,还是做一个复杂的金融计算,都离不开它。很多初学者容易把 Number 理解成一个简单的“数字类型”,但实际上,它有一套自己的规则和方法。
JavaScript 中的数字并不区分整数和浮点数,它统统都是以 64位双精度浮点格式 存储的,这套标准遵循的是 IEEE 754。这意味着,你在代码里写的 10 和 10.0,在 JavaScript 引擎看来,存储方式是一样的。
创建数字有两种方式,你可以根据自己的习惯或者项目规范来选择:
// 代码号学习编程:直接量声明,最常用,性能好
let courseScore = 98; // 整数
let coursePrice = 19.9; // 浮点数
let courseViews = 2.5e4; // 科学计数法,输出: 25000
// 使用 Number 构造函数创建对象,不常用,但有助于理解
let totalStudents = new Number(1024); // 这是一个对象,而不是原始值
console.log(courseScore, coursePrice, courseViews); // 输出: 98 19.9 25000
console.log(totalStudents); // 输出: [Number: 1024]
需要留意的是,使用 new Number() 创建的是一个 Number 对象,而直接赋值得到的是一个原始类型的数字。虽然它们在很多情况下可以混用,但在进行严格的类型判断(比如 ===)时,结果是不一样的。在日常开发中,我更建议直接使用字面量的方式,代码更简洁,也不容易引入预期之外的类型判断问题。
边界在哪里:Number 的内置常量
在处理数字时,最怕的就是遇到“超出范围”的情况。JavaScript 提供了一组常量,帮我们标识出数字的边界。这些常量是 Number 对象的静态属性,直接调用即可。
| 常量 | 说明 | 个人经验点 |
|---|---|---|
Number.MIN_VALUE |
小的正数(约 5e-324),不是负数。 | 别误以为它是“小值”,它代表的是最接近 0 的正数。 |
Number.MAX_VALUE |
较大的正数(约 1.8e+308)。 | 如果计算结果超出这个值,就会变成 Infinity。 |
Number.POSITIVE_INFINITY |
正无穷大,在溢出时返回。 | 比如 1e309 的结果就是这个。 |
Number.NEGATIVE_INFINITY |
负无穷大。 | 比如 -1e309 的结果。 |
Number.NaN |
非数字,表示一个未定义或不可表示的值。 | 常见于解析失败时,比如 parseInt('abc')。 |
理解这些边界值,能帮你写出更健壮的代码。,在做数值校验时,判断一个值是不是 NaN,要用 isNaN() 函数,而不能直接 x === NaN,因为 NaN 是唯一一个不等于自身的值。
实用派:Number 的核心方法详解
Number 对象提供的方法,主要分两类:一类是判断型,用于校验;另一类是格式化型,用于展示。
1. 判断数字的有效性
有时候从用户输入或接口返回的数据,不一定是我们期望的合法数字。这时候就需要下面这些方法出场了。
// 代码号学习编程:校验用户输入示例
let userInput = " 123 "; // 模拟用户输入
let parsedNumber = Number.parseFloat(userInput);
// isFinite() 判断是否是有限数字
console.log(Number.isFinite(parsedNumber)); // 输出: true
console.log(Number.isFinite(Infinity)); // 输出: false
// isInteger() 判断是否为整数
console.log(Number.isInteger(parsedNumber)); // 输出: true
console.log(Number.isInteger(3.14)); // 输出: false
// parseInt() 和 parseFloat() 转换字符串
console.log(Number.parseInt("3.14 years")); // 输出: 3 (只取整数部分)
console.log(Number.parseFloat("3.14 years")); // 输出: 3.14 (解析到非数字为止)
有一点值得留意:Number.isNaN() 和全局的 isNaN() 行为略有不同。全局的 isNaN() 会先尝试将参数转换为数字,而 Number.isNaN() 不会进行类型转换,只有值本身是 NaN 时才返回 true。考虑到代码的严谨性,现在更倾向于使用 Number.isNaN()。
2. 格式化数字的显示
在处理金额、百分比或者科学计数时,我们需要控制数字的小数位数或展示格式。
let coursePrice = 123.45678;
// toFixed() 保留指定位数小数,返回字符串
console.log(coursePrice.toFixed(2)); // 输出: "123.46" (四舍五入)
// toPrecision() 指定有效数字的位数
console.log(coursePrice.toPrecision(4)); // 输出: "123.5" (总长度为4)
// toExponential() 转为科学计数法
console.log(coursePrice.toExponential(2)); // 输出: "1.23e+2"
// toString() 转换为字符串,可以传基数 (2-36)
let number = 255;
console.log(number.toString(16)); // 输出: "ff" (十六进制)
这里有一个常见的误区:toFixed() 返回的是字符串,而不是数字。如果你需要继续计算,记得用 Number() 或者 parseFloat() 把它转回来。我曾在项目中见过因为忘记转换直接拼接字符串而导致的页面显示错误,排查了很久才发现是这个细节。
深入一点:浮点数计算的与建议
前面提到了 IEEE 754 标准,这个标准在带来便利的同时,也有一个经典的困扰:浮点数精度问题。
console.log(0.1 + 0.2); // 输出: 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // 输出: false
这不是 JavaScript 的 bug,而是二进制浮点数表示的固有限制。在做需要高精度的计算(如金融系统)时,直接使用浮点数会带来误差。
应对策略
-
整数化计算:将小数转换为整数进行计算。比如涉及金额,可以以“分”为单位,全部用整数运算,之后再除以100。
-
使用第三方库:对于复杂的高精度计算,可以使用像
big.js或decimal.js这样的库,它们专门处理十进制精度问题。 -
保留误差范围:在做相等判断时,允许一个很小的误差值。
// 代码号学习编程:使用误差范围判断浮点数相等
function areNumbersEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON; // EPSILON 是 JavaScript 能表示的小精度差
}
console.log(areNumbersEqual(0.1 + 0.2, 0.3)); // 输出: true
本节课程知识要点
-
声明方式:优先使用字面量
let num = 10,避免使用new Number(),保持数据类型的纯粹性。 -
边界常量:熟悉
MAX_VALUE、MIN_VALUE、NaN等常量,用于防御性编程和错误判断。 -
类型转换:使用
Number.parseInt()和Number.parseFloat()解析字符串,它们比一元运算符+更具可读性,且能指定进制。 -
数值格式化:根据展示需求选择
toFixed()、toPrecision()等方法,注意返回值类型为字符串。 -
精度处理:意识到浮点数计算存在精度误差,对于严格要求的场景,采用整数化或借助专用库来处理。
掌握 Number 对象,不仅仅是学会它的 API,更是要理解数字在计算机中是如何存储和计算的。这样,你才能在日常的代码号学习编程中,写出既符合预期又健壮的程序。