字符串转数字
JavaScript 内部在进行 字符串转数字 时,主要依赖 ToNumber
抽象操作,该操作遵循 ECMAScript 规范,并且不同的转换方式(Number()
、parseInt()
、parseFloat()
、+
一元运算符等)在底层实现上有所不同。
1. ToNumber
规则
根据 ECMAScript 规范(ECMA-262),字符串转数字的规则如下:
字符串值 | 转换结果 |
---|---|
"" (空字符串) | 0 |
"-0" | -0 |
"+0" | 0 |
"-123" | -123 |
"123" | 123 |
" 123 " (前后空格) | 123 |
"123.45" | 123.45 |
"1e3" | 1000 (科学计数法) |
"0x10" | 16 (十六进制) |
"Infinity" | Infinity |
"-Infinity" | -Infinity |
"NaN" | NaN |
"123abc" | NaN (无法完整解析) |
"0b101" | NaN (不支持二进制) |
null | 0 |
undefined | NaN |
true | 1 |
false | 0 |
2. 不同方法的底层转换
(1) Number(str)
- 遵循
ToNumber
规则,会转换合法数字字符串,但不支持部分匹配(如"123abc"
→NaN
)。 - 规范实现:
- 去掉前后空格。
- 识别
+/-
符号。 - 解析十进制、科学计数法、十六进制(
0x
)。 - 其他返回
NaN
。
js
console.log(Number("123")); // 123
console.log(Number(" 123 ")); // 123
console.log(Number("0x10")); // 16
console.log(Number("123abc")); // NaN
console.log(Number("1e3")); // 1000
(2) parseInt(str, radix)
- 逐字符解析,遇到非数字字符 停止,不报错(如
"123abc"
→123
)。 - 可指定 进制(如
0x
→ 16 进制)。 - 规范实现:
- 跳过前导空格。
- 解析
+/-
符号。 - 解析
0x
(十六进制)。 - 遇到 非法字符 停止。
js
console.log(parseInt("123abc")); // 123 ✅
console.log(parseInt("0x10")); // 16 ✅ (十六进制)
console.log(parseInt("0123", 10)); // 123 ✅ (显式十进制)
console.log(parseInt("0b101")); // 0 ❌ (不支持二进制)
console.log(parseInt("Infinity")); // NaN ❌
(3) parseFloat(str)
- 类似
parseInt()
,但支持 小数点 和 科学计数法。 - 解析 直到非法字符,不会报错。
js
console.log(parseFloat("123.45abc")); // 123.45 ✅
console.log(parseFloat("1e3")); // 1000 ✅
console.log(parseFloat("0.1e2")); // 10 ✅
console.log(parseFloat("Infinity")); // Infinity ✅
console.log(parseFloat("0b101")); // 0 ❌
(4) +str
(一元加号)
- 最简洁,等同于
Number(str)
,遵循ToNumber
规则。
js
console.log(+"123"); // 123 ✅
console.log(+" 123 "); // 123 ✅
console.log(+"0x10"); // 16 ✅
console.log(+"123abc"); // NaN ❌
console.log(+"1e3"); // 1000 ✅
3. ToNumber
处理非字符串情况
JavaScript 隐式类型转换 会调用 ToNumber()
,它不仅限于字符串,还适用于布尔值、null
、undefined
、对象等:
值 | Number() 转换结果 |
---|---|
true | 1 |
false | 0 |
null | 0 |
undefined | NaN |
{} | NaN |
[] | 0 |
['123'] | 123 |
['123abc'] | NaN |
js
console.log(Number(true)); // 1
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
console.log(Number([])); // 0
console.log(Number(["123"])); // 123
console.log(Number(["123abc"])); // NaN
console.log(Number({})); // NaN
4. 性能比较
方法 | 速度 | 特性 | 适用场景 |
---|---|---|---|
Number(str) | ⭐⭐⭐⭐ | 严格转换,不支持部分匹配 | 需要严格转换时 |
+str | ⭐⭐⭐⭐⭐ | 最快,等同 Number(str) | 需要快速转换时 |
parseInt(str) | ⭐⭐⭐ | 支持部分匹配,遇到非数字停止 | 解析整数时 |
parseFloat(str) | ⭐⭐⭐ | 支持小数,遇到非数字停止 | 解析小数时 |
js
console.time("Number");
for (let i = 0; i < 1e6; i++) Number("123");
console.timeEnd("Number");
console.time("+");
for (let i = 0; i < 1e6; i++) +"123";
console.timeEnd("+");
结果表明 +str
是最快的。
5. 结论
Number(str)
和+str
是 最严格 的转换方式,不能解析123abc
,但速度最快。parseInt(str)
和parseFloat(str)
可部分匹配,但 性能略低。ToNumber
规则处理null
→0
,undefined
→NaN
,注意隐式转换。
在实际开发中:
- 需要严格转换 →
Number(str)
或+str
- 允许部分匹配 →
parseInt()
/parseFloat()
- 处理 JSON 解析 →
JSON.parse(str)