JavaScript字符串转数字的7种方法详解与性能对比

7309 Views

在JavaScript开发中,字符串与数字之间的类型转换是每个开发者必须掌握的基础技能。本文将从底层原理到实际应用场景,深度剖析7种字符串转数字的方法及其隐藏特性,并通过20+个代码示例揭示常见陷阱。

一、Number() 构造函数

console.log(Number("42")); // 42

console.log(Number("3.14")); // 3.14

console.log(Number("0xFF")); // 255 (十六进制)

console.log(Number("123e-2")); // 1.23

console.log(Number("")); // 0

console.log(Number("12a")); // NaN

console.log(Number(true)); // 1

console.log(Number(false)); // 0

核心原理:

执行ECMAScript标准的ToNumber抽象操作

空字符串转换为0

忽略前后空格但中间有非数字字符返回NaN

支持科学计数法和进制转换

性能基准测试(Chrome 115):

// 测试100万次转换

console.time("Number");

for(let i=0; i<1e6; i++) Number("123.45");

console.timeEnd("Number"); // ~35ms

二、一元加号运算符

console.log(+"42"); // 42

console.log(+"3.14"); // 3.14

console.log(+"0o77"); // 63 (八进制)

console.log(+"Infinity"); // Infinity

console.log(+"12px"); // NaN

console.log(+""); // 0

console.log(+null); // 0

console.log(+undefined); // NaN

与Number()的区别:

const str = "123";

console.log(Number(str) === +str); // true

性能对比:

console.time("Unary Plus");

for(let i=0; i<1e6; i++) +"123.45";

console.timeEnd("Unary Plus"); // ~32ms (比Number稍快)

三、parseInt() 深度解析

console.log(parseInt("42px")); // 42

console.log(parseInt("101", 2)); // 5 (二进制)

console.log(parseInt("0x1F")); // 31

console.log(parseInt("3.14")); // 3

console.log(parseInt(" 123")); // 123

console.log(parseInt("abc")); // NaN

关键特性:

自动截断非数字后缀

第二个参数指定基数(2-36)

0x开头的字符串识别为十六进制

ES5后前导0不再默认八进制

常见陷阱:

parseInt("09", 10); // 9 (正确)

parseInt("09"); // 9 (ES5+)

parseInt("0.1"); // 0 (不是0.1!)

parseInt(1/0, 19); // 18 (因为1e308在19进制中的解析)

四、parseFloat() 的特别之处

console.log(parseFloat("3.14.15")); // 3.14

console.log(parseFloat("3e2")); // 300

console.log(parseFloat("0xFF")); // 0 (不识别十六进制)

console.log(parseFloat("123a")); // 123

console.log(parseFloat("Infinity"));// Infinity

与Number()对比: | 特征 | parseFloat | Number | |----------------|------------|-----------| | 前导空格 | 忽略 | 忽略 | | 数字+非数字 | 截断 | NaN | | 空字符串 | NaN | 0 | | null | NaN | 0 | | 十六进制 | 不识别 | 识别 |

五、位运算符的妙用

console.log(~~"12.99"); // 12

console.log("5.87" | 0); // 5

console.log("123" >> 0); // 123

console.log(+"Infinity" | 0); // 0

实现原理:

所有位运算符操作前都会执行ToInt32转换

相当于先执行Number()再执行按位操作

只能得到32位有符号整数

适用场景:

快速取整

将NaN转换为0

性能敏感场景(比parseInt快3倍)

六、Date对象的转换技巧

console.log(new Date("2023").getTime()); // 时间戳转换

console.log(Date.parse("2023-07-01")); // 1688169600000

特殊用法:

const timestamp = +new Date("2023-01-01");

console.log(timestamp); // 1672531200000

七、现代ES6+方法

console.log(Number.parseInt === parseInt); // true

console.log(Math.trunc("42.9")); // 42

console.log(BigInt("123")); // 123n

新型API对比: | 方法 | 返回值类型 | 特性 | |------------------|------------|------------------------| | Number.parseInt | number | 同全局parseInt | | Number.parseFloat| number | 同全局parseFloat | | Math.trunc | number | 直接截断小数部分 | | BigInt | bigint | 处理大于2^53的整数 |

高级应用场景

表单验证:

function validateNumber(input) {

const num = +input;

return typeof num === 'number' &&

!isNaN(num) &&

isFinite(num);

}

科学计算精度处理:

function toPrecision(str, precision=2) {

return (+str).toFixed(precision);

}

大数据转换优化:

// 使用TypedArray进行批量转换

const strArray = ["1", "2", "3"];

const float32 = new Float32Array(strArray.length);

strArray.forEach((s, i) => float32[i] = +s);

性能终极对决

// 测试100万次转换(Node.js 18)

Method | Time(ms)

----------------|---------

Number() | 38

parseInt | 72

parseFloat | 68

一元加号 | 35

位运算(|0) | 28

Math.floor | 45

优化建议:

优先使用一元加号或位运算符

避免在循环中使用parseInt/parseFloat

对已知格式的字符串使用定制解析

常见陷阱及解决方案

八进制陷阱:

parseInt("012"); // 10 (ES5+)

parseInt("012", 8); // 10 (正确八进制解析)

大数精度丢失:

console.log(+"9007199254740993"); // 9007199254740992

// 解决方案:

BigInt("9007199254740993") // 9007199254740993n

自动类型转换问题:

1 + "2" = "12" // 字符串拼接

1 + +"2" = 3 // 正确数值相加

非数字的NaN判断:

isNaN(+"abc") // true

Number.isNaN(+"abc") // true (推荐)

Object.is(+'abc', NaN) // true

终极选择指南

场景

推荐方法

示例

严格数字验证

Number()

Number("123")

CSS单位剥离

parseInt

parseInt("100px")

浮点转换

parseFloat

parseFloat("3.14")

性能敏感代码

一元加号

+"123"

取整操作

位运算符

"45.6" | 0

大整数处理

BigInt

BigInt("123456789")

日期转换

Date.parse()

Date.parse(dateStr)

灵棋经在线占卜-灵棋经详解
2026业主真实实测:四款热门活性锰除醛片使用口碑评价