arduino
console.log(['1', '2', '3'].map(parseInt));
// 输出:[1, NaN, NaN] 而不是预期的 [1, 2, 3]
看到这行代码的输出,相信很多 JS 萌新会当场表演一个"瞳孔地震":说好的字符串转数字呢?NaN 是哪里冒出来的?今天我们就来扒一扒这个经典面试题背后的秘密!
🧩 案发现场还原
想象一下场景:你开了一家奶茶店,顾客们排队点单:
css
顾客队列 = ['珍珠奶茶', '芋圆奶茶', '芝士莓莓']
你训练了三个店员做饮料:
ini
店员A = 做珍珠奶茶
店员B = 做芋圆奶茶
店员C = 做芝士莓莓
但当他们开工时:
less
店员A('珍珠奶茶', 0, 整个菜单) // ✅ 完美
店员B('芋圆奶茶', 1, 整个菜单) // ❌ 突然失忆
店员C('芝士莓莓', 2, 整个菜单) // ❌ 开始胡言乱语
这像极了 map
和 parseInt
的配合翻车现场!
🔍 关键角色档案
1. map
:数组的流水线工人
javascript
[1, 2, 3].map((当前元素, 索引, 整个数组) => {
return 加工后的元素
})
- 必须给工人明确的操作说明书(回调函数)
- 工人会默认为说明书传递三个参数(即使你没写)
2. parseInt
:挑食的数字转换器
scss
parseInt(字符串, 进制)
-
第一个参数:要转换的字符串
-
第二个参数:进制基数(2-36)
-
特殊规则:
- 基数为 0 时 → 当作十进制
- 基数小于 2 或大于 36 → 返回 NaN
- 基数未提供 → 自动推断(可能翻车!)
💥 案发过程全解析
当我们执行 ['1','2','3'].map(parseInt)
时:
迭代次数 | 实际调用 | 等效代码 | 结果 | 原因分析 |
---|---|---|---|---|
第一次 | parseInt('1', 0) |
parseInt('1', 10) |
1 | 0 进制被当作十进制处理 |
第二次 | parseInt('2', 1) |
parseInt('2',1) |
NaN | 1 进制不存在(最小为2进制) |
第三次 | parseInt('3', 2) |
parseInt('3',2) |
NaN | 二进制中不允许出现数字 3 |
就像让川菜师傅按粤菜菜谱做菜------参数错配引发灾难!
🧪 亲自验证案发现场
javascript
// 模拟 map 传参
console.log(parseInt('1', 0)); // 1
console.log(parseInt('2', 1)); // NaN(1进制?不存在的!)
console.log(parseInt('3', 2)); // NaN(二进制里哪来的3?)
🛠 修复方案:给它们安排"相亲中介"
方案 1:显式控制约会参数
scss
['1', '2', '3'].map((num) => parseInt(num, 10))
// 输出:[1, 2, 3] ✅
相当于明确告诉parseInt:"别管map给你塞什么小纸条,老老实实用十进制!"
方案 2:介绍更合适的对象(Number)
scss
['1', '2', '3'].map(Number)
// 输出:[1, 2, 3] ✅
Number 是个老实人:不管传几个参数,只看第一个!
方案 3:自定义约会规则
javascript
['1', '2', '3'].map(n => parseInt(n))
// 输出:[1, 2, 3] ✅
箭头函数:屏蔽多余参数,避免进制误会
🌟 避免踩坑的黄金法则
-
永远显式指定进制
parseInt
的自动推断是个坑:javascriptparseInt('08') // 旧版JS中返回0(误判为八进制) parseInt('08', 10) // 安全返回8
-
警惕多参数陷阱
当函数作为高阶函数的参数时:
scss// 可能翻车的操作 [1.2, 2.3, 3.4].map(parseFloat) // 实际变成 [parseFloat(1.2,0), parseFloat(2.3,1)...] // 但 parseFloat 会忽略第二个参数 → 安全 ✅
-
善用箭头函数护盾
c// 安全写法模板 arr.map(item => targetFunction(item))
💡 举一反三实验室
思考以下代码输出什么:
scss
['10','10','10','10'].map(parseInt)
点击查看解析
javascript
parseInt('10', 0) // 10进制 → 10
parseInt('10', 1) // 1进制 → NaN
parseInt('10', 2) // 2进制 → 2(1*2 + 0)
parseInt('10', 3) // 3进制 → 3(1*3 + 0)
// 输出:[10, NaN, 2, 3]
进制参数的索引会不断递增!
🚀 总结:参数匹配的重要性
这次翻车事件本质是参数协议不匹配:
map
说:"我给你三个参数(值,索引,数组)"parseInt
说:"我只看前两个(字符串,进制)"
在编程世界和现实生活中同理------清晰的沟通规则避免误会。所以下次使用函数时,记得确认它们的"交流规则"哦!
终极忠告:
map(parseInt)
的组合就像让相声演员唱京剧,不是不能配合,但必须重新设计唱腔!🎭