购物车里数量是字符串 2,用户点了加一,代码写 num + 1,页面显示 21。加号一见字符串就变成拼接,这种事每年都要重演几回。
Number 是最直接的写法
const n = Number('12.5');整串能解析成数字就返回数字,否则返回 NaN。空字符串返回 0,这点要留心,表单没填时会被当成 0 混进计算。首尾空白会被忽略,中间带空格就是 NaN。
转换完必须判一次,否则 NaN 会顺着运算一路传下去:
if (Number.isNaN(n)) { return; }parseInt 和 parseFloat 只读一半
parseInt('12px') 得 12,parseFloat('3.5元') 得 3.5,遇到非法字符就停。它们适合从带单位的字符串里刮数字,不适合做校验。真要用 parseInt,第二个参数写上 10,避免历史遗留的进制问题。
另一个细节,parseInt 会先把参数转成字符串,传 1e21 这种大数会得到 1,看着莫名其妙。
一元加号只是简写。加号放在变量前面等价于 Number,短一点,可读性差一点。连写两个加号时容易看错,团队代码里不如老实写 Number。
小数和大整数各有一个坑
0.1 加 0.2 得到 0.30000000000000004,这是浮点表示的问题,跟转换函数无关。比较时看差值绝对值是否小于一个极小值,展示金额先 toFixed(2) 再转字符串。
超过 2 的 53 次方的整数,转成 Number 就开始丢精度。订单号、身份证号这种长数字,先问一句能不能不转,必须参与计算就用 BigInt,或者全程按字符串传递。
数据从哪来,决定要不要转
从 JSON 里取出来的数字本来就是数字类型,不用转;localStorage 和 URL 查询参数拿到的一律是字符串,这两处才是转换的主战场。批量处理数组可以写 list.map(Number),空串会被转成 0,最好再 filter 一遍把空值滤掉。
判断:用户输入统一走 Number 加 Number.isNaN,带单位的字符串用 parseFloat,金额按分存整数,长 ID 别碰 Number。