12k
All articles

如何在 JavaScript 中解析数字

对比 parseInt、parseFloat、Number 和 BigInt 将字符串转换为数字的方法,规避导致静默错误的边界情况。

OpenReplay Team
OpenReplay Team
如何在 JavaScript 中解析数字

当你从表单字段、URL 参数或 JSON API 响应中读取值时,它几乎总是以字符串形式到达。在对其进行任何数学运算之前,你需要将其转换为数字。JavaScript 为你提供了几种实现方法,它们的行为差异足以导致选择错误的方法会引发细微的 bug。本文介绍了主要方法、何时使用每种方法,以及最常困扰开发者的边界情况。

核心要点

  • parseInt()parseFloat() 执行部分解析,从左到右读取并在第一个无效字符处停止——适用于像 "24px" 这样的字符串。
  • Number() 和一元 + 运算符要求整个字符串有效,否则返回 NaN——非常适合从 API 数据进行严格转换。
  • 始终向 parseInt() 传递基数参数,并始终使用 Number.isNaN() 而不是全局 isNaN() 来验证结果。
  • 对于超出 Number.MAX_SAFE_INTEGER 的整数使用 BigInt(),并在解析前规范化区域格式化的字符串。

快速对比:JavaScript 字符串转数字的转换方法

方法输入 "42px"输入 "3.14"输入 ""输入 "abc"
parseInt("42px", 10)423NaNNaN
parseFloat("42px")423.14NaNNaN
Number("42px")NaN3.140NaN
+"42px"NaN3.140NaN

parseInt():整数的部分解析

parseInt(string, radix) 从左到右读取字符,并在遇到无法解析的内容时立即停止。这使得它对于像 "24px""10rem" 这样数字在前的字符串很有用。

parseInt("24px", 10)   // 24
parseInt("3.99", 10)   // 3  (小数点停止解析)
parseInt("abc", 10)    // NaN (第一个字符无效)

始终传递基数参数。 如果不传递,parseInt 会将以 0x 开头的字符串视为十六进制,否则以十进制解析。虽然现代引擎默认为十进制,但省略基数是一个众所周知的 bug 来源,并且会使你的意图不明确。

parseInt("0xFF", 16)   // 255 — 显式十六进制解析
parseInt("011", 10)    // 11  — 基数防止歧义

一个不明显的行为:parseInt"6.022e23" 的小数点处停止,因此 parseInt("6.022e23", 10) 返回 6,而不是 602200000000000000000000。不要使用 parseInt 来截断大型浮点数。请改用 Math.trunc()


parseFloat():小数的部分解析

parseFloat() 的工作方式与 parseInt 相同,但保留小数部分。它没有基数参数,始终以十进制解析。

parseFloat("3.14rem")  // 3.14
parseFloat("1e3")      // 1000 — 理解科学计数法
parseFloat("px10")     // NaN  — 第一个字符无效

当输入可能包含小数值并且你想保留它时,使用 parseFloat


Number() 和一元 +:严格转换

Number() 和一元 + 运算符都要求整个字符串是有效数字。如果其中任何部分无效,你会得到 NaN。在处理 API 响应或经过验证的表单数据时,这种严格性是一个优势,因为部分解析会是一个静默错误。

Number("42")     // 42
Number("3.14")   // 3.14
Number("42px")   // NaN — 比 parseInt 更严格
Number("")       // 0   — 注意这一点
+"42"            // 42  — 行为相同,语法更短

空字符串边界情况在表单处理中很重要。Number("") 返回 0 而不是 NaN,这可能会掩盖缺失值。在转换前始终检查空输入。


数字分隔符在运行时不起作用

JavaScript 源代码允许 1_000_000 作为数字字面量,但该语法不适用于字符串解析。

parseInt("1_000", 10)   // 1 — 解析在下划线处停止
Number("1_000")         // NaN

如果你的 API 或用户输入使用下划线作为千位分隔符,请先使用 str.replace(/_/g, "") 将其删除。


BigInt():解析大整数

JavaScript 的 Number 类型在超出 Number.MAX_SAFE_INTEGER(2⁵³ − 1)后会失去精度。对于大于该值的数字——数据库 ID、加密值、金融整数——使用 BigInt()

BigInt("9007199254740993")   // 9007199254740993n — 精确
Number("9007199254740993")   // 9007199254740992  — 差一

直接将字符串传递给 BigInt()。不要先通过 parseInt 传递,因为此时精度已经丢失。请注意,BigInt 值不能在算术运算中与常规 Number 值混合使用,除非进行显式转换。


区域感知解析

JavaScript 没有内置函数来解析区域格式化的数字,如 "1.234,56"(在德语或西班牙语区域设置中常见)。你需要在解析前手动规范化字符串:

const raw = "1.234,56"
const normalized = raw.replace(/\./g, "").replace(",", ".")
parseFloat(normalized) // 1234.56

你应该使用哪种方法?

  • 带单位的用户输入或 CSS 值parseInt(str, 10)parseFloat()
  • API 响应或严格验证的数据Number() 或一元 +
  • 超出 2⁵³ − 1 的整数BigInt()
  • 始终在使用结果前验证其不是 NaN:
const qty = parseInt(input, 10)
if (Number.isNaN(qty)) {
  // 处理无效输入
}

使用 Number.isNaN(),而不是全局 isNaN()。全局版本会先强制转换其参数,这意味着 isNaN("") 返回 false,即使 "" 不是数字。


结论

正确的 JavaScript 数字解析方法取决于你对输入的了解。当部分解析是可接受和预期的时,使用 parseIntparseFloat。当整个字符串必须是有效数字时,使用 Number() 或一元 +。当大整数的精度很重要时,使用 BigInt()。在所有情况下,在使用结果之前都要检查 NaN

常见问题

JavaScript 中 parseInt 和 Number 有什么区别?

parseInt 从左到右读取字符串,并在遇到无法解释为整数一部分的第一个字符时停止。Number 要求整个字符串是有效的数字值。例如,parseInt('42px') 返回 42,而 Number('42px') 返回 NaN。使用 parseInt 进行部分解析,使用 Number 进行严格转换。

为什么空字符串的 Number 返回 0 而不是 NaN?

ECMAScript 规范定义空字符串在传递给 Number 或一元加运算符时转换为 0。这可能会掩盖缺失的表单值。在将输入字符串转换为数字之前,始终检查其是否为空,以避免将空白字段视为零。

何时应该使用 BigInt 而不是 Number 进行解析?

当整数超过 Number.MAX_SAFE_INTEGER(即 2 的 53 次方减 1)时使用 BigInt。超过该阈值,Number 会失去精度并可能静默舍入值。直接将数字字符串传递给 BigInt,而不是先通过 parseInt 或 Number 转换,因为在该中间步骤期间精度会丢失。

为什么应该使用 Number.isNaN 而不是全局 isNaN 函数?

全局 isNaN 在检查之前会强制转换其参数,这会产生误导性结果。例如,空字符串的 isNaN 返回 false,因为空字符串强制转换为 0。Number.isNaN 跳过强制转换,仅在值确实是 NaN 时返回 true,使其成为验证的可靠选择。

Open-source session replay

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.