TypeScript 是 JavaScript 的一个超集,它添加了静态类型检查和其他一些特性来帮助开发者编写更可靠、更易于维护的代码。在 TypeScript 中,Number
类型用于表示数值数据类型,包括整数和浮点数。TypeScript 的 Number
类型对应于 JavaScript 的原始数值类型。
Number 对象与基本 number 类型的区别
在 TypeScript(以及 JavaScript)中,number
类型和 Number
对象有明显的区别。理解这两者之间的差异对于正确使用数值类型非常重要。
基本 number 类型
- 原始值 :
number
是一种原始数据类型,它用于表示数值,包括整数和浮点数。它是直接存储的数值,而不是对象。 - 性能更高 :因为
number
是原始值,所以它们的处理速度更快,占用的内存也更少。 - 不可变性 :作为原始值,
number
一旦创建就不能改变。每次对number
进行操作都会产生一个新的数值。 - 用法简单 :当你只需要一个简单的数值时,通常会使用
number
类型。
typescript
let age: number = 30;
Number 对象
- 包装对象 :
Number
是一个构造函数,可以用来创建一个包装了原始数值的对象。它提供了额外的方法和属性来操作数值。 - 包含静态方法和属性 :
Number
对象包含了多个静态方法和属性,如Number.MAX_VALUE
,Number.MIN_VALUE
,Number.isNaN()
, 等等。 - 可拥有属性 :由于是对象,
Number
实例可以拥有属性和方法,尽管这在实际开发中很少见。 - 性能较低 :相比于原始的
number
类型,Number
对象的操作可能会稍微慢一些,并且消耗更多的内存。 - 自动拆箱 :JavaScript 在需要的时候会自动将
Number
对象转换为原始的number
类型(称为"拆箱"),例如进行数学运算时。
typescript
let numObj = new Number(30);
console.log(numObj); // 输出: Number { 30 }
注意事项
- 不要随意使用
new Number()
:在大多数情况下,没有必要使用new Number()
来创建数值的包装对象。直接使用原始的number
类型即可。使用new Number()
可能会导致意外的行为,特别是在比较相等性时,因为两个不同的Number
对象即使包含相同的数值也不会被认为是相等的。
typescript
let a = new Number(10);
let b = new Number(10);
console.log(a == b); // false, 因为它们是不同的对象
console.log(a === b); // false, 同上
console.log(a.valueOf() === b.valueOf()); // true, 比较的是内部的原始值
- 静态方法的使用 :你可以直接通过
Number
构造函数访问静态方法,而不需要创建Number
的实例。例如:
typescript
let parsedInt = Number.parseInt("123"); // 使用静态方法 parseInt
总之,在日常编程中,你应该优先选择使用基本的 number
类型,除非你有特定的理由需要使用 Number
对象。
Number 对象属性
Number
对象在 TypeScript 和 JavaScript 中提供了一些有用的静态属性,这些属性可以直接通过 Number
构造函数访问,而不需要创建 Number
的实例。以下是 Number
对象的一些常用属性:
静态属性
-
Number.EPSILON
: 表示1与大于1的最小浮点数之间的差异,用于比较浮点数以确定它们是否足够接近。typescriptconsole.log(Number.EPSILON); // 输出: 2.220446049250313e-16
-
Number.MAX_SAFE_INTEGER
: 可以安全使用的最大整数值(2^53 - 1)。typescriptconsole.log(Number.MAX_SAFE_INTEGER); // 输出: 9007199254740991
-
Number.MIN_SAFE_INTEGER
: 可以安全使用的最小整数值(-(2^53 - 1))。typescriptconsole.log(Number.MIN_SAFE_INTEGER); // 输出: -9007199254740991
-
Number.MAX_VALUE
: 能够表示的最大正数。typescriptconsole.log(Number.MAX_VALUE); // 输出: 1.7976931348623157e+308
-
Number.MIN_VALUE
: 能够表示的最接近零的正数(非零)。typescriptconsole.log(Number.MIN_VALUE); // 输出: 5e-324
-
Number.NaN
: 表示"不是数字"的特殊值。typescriptconsole.log(Number.NaN); // 输出: NaN
-
Number.NEGATIVE_INFINITY
: 表示负无穷大。typescriptconsole.log(Number.NEGATIVE_INFINITY); // 输出: -Infinity
-
Number.POSITIVE_INFINITY
: 表示正无穷大。typescriptconsole.log(Number.POSITIVE_INFINITY); // 输出: Infinity
使用注意事项
当使用 Number
对象的静态属性时,直接通过 Number
访问即可,不需要也不应该使用 new Number()
来创建对象实例来访问这些属性。例如:
typescript
// 正确用法
console.log(Number.MAX_VALUE);
// 错误用法,不应该这样做
let numObj = new Number(42);
console.log(numObj.MAX_VALUE); // 这不会工作,因为 MAX_VALUE 是静态属性
以上列出的属性都是只读的,并且是静态的,意味着它们属于 Number
构造函数本身而不是它的实例。因此,当你需要使用这些常量时,总是直接从 Number
访问它们。
Number 对象方法
Number
对象在 TypeScript 和 JavaScript 中提供了许多静态方法和实例方法,用于数值的解析、格式化以及数值属性的检查等操作。这些方法可以帮助开发者更方便地处理数值类型的数据。以下是 Number
对象的一些常用方法:
静态方法
-
Number.parseFloat(string)
: 将一个字符串解析为浮点数。typescriptconsole.log(Number.parseFloat("123.45")); // 输出: 123.45
-
Number.parseInt(string, radix)
: 将一个字符串解析为整数。radix
参数是可选的,指定了解析时所用的进制(例如,10 表示十进制)。typescriptconsole.log(Number.parseInt("101", 2)); // 输出: 5 (二进制)
-
Number.isNaN(value)
: 检查给定值是否为NaN
。它比全局的isNaN()
函数更为严格,因为后者会尝试将非数字参数转换为数字再进行判断。typescriptconsole.log(Number.isNaN(NaN)); // true console.log(Number.isNaN(123)); // false
-
Number.isFinite(value)
: 检查给定值是否为有限数值(既不是Infinity
也不是-Infinity
或NaN
)。typescriptconsole.log(Number.isFinite(100)); // true console.log(Number.isFinite(Infinity)); // false
-
Number.isInteger(value)
: 检查给定值是否为整数。typescriptconsole.log(Number.isInteger(100)); // true console.log(Number.isInteger(100.1)); // false
-
Number.isSafeInteger(value)
: 检查给定值是否为安全整数(即,在Number.MIN_SAFE_INTEGER
和Number.MAX_SAFE_INTEGER
之间的整数)。typescriptconsole.log(Number.isSafeInteger(9007199254740991)); // true console.log(Number.isSafeInteger(9007199254740992)); // false
实例方法
对于通过 new Number(value)
创建的 Number
对象,或者直接使用原始数值(由于自动装箱机制),你可以调用以下方法:
-
.toFixed(fractionDigits)
: 返回指定小数位数的字符串表示形式。typescriptlet num = 123.456; console.log(num.toFixed(2)); // "123.46"
-
.toExponential(fractionDigits)
: 返回以指数记法表示的字符串。typescriptlet num = 123; console.log(num.toExponential(2)); // "1.23e+2"
-
.toPrecision(precision)
: 返回指定精度的有效数字表示的字符串。typescriptlet num = 123.456; console.log(num.toPrecision(4)); // "123.5"
-
.toString(radix)
: 返回数值的字符串表示,radix
参数是可选的,指定了转换时使用的进制。typescriptlet num = 255; console.log(num.toString(16)); // "ff" (十六进制)
-
.toLocaleString(locales, options)
: 根据本地化的格式返回数值的字符串表示。locales
参数可以指定语言环境,options
可以指定格式选项。typescriptlet num = 123456.789; console.log(num.toLocaleString('en-US')); // "123,456.789"
请注意,虽然你可以创建 Number
对象来访问这些方法,但在大多数情况下,直接在原始数值上调用这些方法就足够了。JavaScript 的自动装箱机制会临时将原始数值包装成对象,以便能够调用这些方法。因此,通常没有必要显式地使用 new Number()
构造函数。
Number 对象的使用建议
在 TypeScript(以及 JavaScript)中使用 Number
对象时,有几点建议可以帮助你编写更有效和更可靠的代码:
1. 避免不必要的 Number
对象实例化
-
优先使用原始的
number
类型 :除非有特殊需求,否则应该避免使用new Number()
创建Number
对象。原始数值类型性能更高,且更容易理解。typescript// 不推荐 let numObj = new Number(42); // 推荐 let num = 42;
2. 使用静态方法进行数值处理
-
利用
Number
的静态方法 :Number
提供了多个静态方法来解析字符串、检查数值特性等。直接调用这些静态方法即可,无需创建Number
实例。typescriptconsole.log(Number.parseInt("10")); // 使用静态方法 parseInt console.log(Number.isNaN(NaN)); // 使用静态方法 isNaN
3. 比较相等性时要小心
-
注意相等性比较 :两个不同的
Number
对象即使包含相同的数值也不会被认为是相等的。因此,在比较数值时,应确保它们都是原始类型的number
。typescriptlet a = new Number(10); let b = new Number(10); console.log(a == b); // false, 因为它们是不同的对象 console.log(a.valueOf() === b.valueOf()); // true, 比较的是内部的原始值
4. 使用适当的数值检查方法
-
选择合适的数值检查方法 :根据你的需要选择
Number.isNaN
,Number.isFinite
,Number.isInteger
, 或Number.isSafeInteger
等方法来进行精确的数值属性检查。typescriptconsole.log(Number.isInteger(100)); // true console.log(Number.isSafeInteger(9007199254740991)); // true
5. 格式化输出
-
使用格式化方法 :当需要格式化数值输出时,可以使用
.toFixed()
,.toExponential()
,.toPrecision()
, 和.toLocaleString()
等方法。typescriptlet price = 123.456; console.log(price.toFixed(2)); // "123.46" console.log(price.toLocaleString('en-US', { style: 'currency', currency: 'USD' })); // "$123.46"
6. 处理浮点数精度问题
-
意识到浮点数运算的精度问题 :JavaScript 中的浮点数运算可能会导致精度丢失的问题。如果需要高精度计算,考虑使用第三方库如
decimal.js
。typescriptconsole.log(0.1 + 0.2); // 0.30000000000000004
7. 使用 Number.EPSILON
进行浮点数比较
-
浮点数比较 :对于浮点数的比较,可以使用
Number.EPSILON
来确定两个数是否足够接近,以考虑到浮点数的精度限制。typescriptfunction areCloseEnough(a, b) { return Math.abs(a - b) < Number.EPSILON; } console.log(areCloseEnough(0.1 + 0.2, 0.3)); // true
总结
总的来说,尽量使用原始的 number
类型,并充分利用 Number
构造函数提供的静态方法。只有当你确实需要一个 Number
对象提供的特定功能时,才应该创建 Number
实例。通过遵循这些建议,你可以写出更加高效和不易出错的代码。