引言
在现代 JavaScript 开发中,Array.prototype.map()
是我们日常使用频率极高的数组方法之一。作为 ES6(ECMAScript 2015)中广泛应用的函数式编程工具,map()
提供了一种简洁、声明式的方式来转换数组元素。但你是否曾遇到过使用 map()
结合 parseInt
时出现"意料之外"的结果?本文将带你深入理解 map()
的机制,并揭开这个经典陷阱的真相。
✅ 什么是 map()
?
map()
是数组的内置方法,用于创建一个新数组,其结果是原数组中每个元素调用提供的函数后的返回值。关键特性如下:
- 不修改原数组,返回一个全新的数组。
- 接受一个回调函数 作为参数,该函数会被自动传入三个参数:
currentValue
:当前正在处理的元素。index
:当前元素的索引。array
:调用map()
的原数组。
基本语法:
js
const newArray = array.map((currentValue, index, array) => {
// 返回新值
});
示例:字符串数组转数字数组
js
const strArray = ['1', '2', '3'];
const numArray = strArray.map((num, index, arr) => {
console.log(num, index, arr);
// 输出: '1' 0 ['1','2','3']
// '2' 1 ['1','2','3']
// '3' 2 ['1','2','3']
return Number(num); // 推荐使用 Number()
});
console.log(numArray); // [1, 2, 3]
一切看起来都很正常,对吧?那如果我们换成 parseInt
呢?
⚠️ 经典陷阱:['1','2','3'].map(parseInt)
为什么结果不是 [1,2,3]
?
你可能见过这样的代码:
js
console.log(['1', '2', '3'].map(parseInt)); // 输出:[1, NaN, NaN]
什么?!明明是把字符串转成数字,为什么会得到 NaN
?
🔍 问题出在 parseInt
的参数签名
parseInt(string, radix)
接受两个参数:
string
:要解析的值。radix
:进制基数(2~36),可选,默认为 10。
而 map()
回调函数的第二个参数是当前元素的索引(index)。
所以,当执行 ['1','2','3'].map(parseInt)
时,实际上是这样调用的:
js
parseInt('1', 0) // index = 0 → radix = 0 → 解释为 10 进制 → 1
parseInt('2', 1) // index = 1 → radix = 1 → 无效进制 → NaN
parseInt('3', 2) // index = 2 → radix = 2 → 二进制中 '3' 不合法 → NaN
因此结果是 [1, NaN, NaN]
。
💡 小知识:
parseInt('1', 0)
中radix=0
被视为10
,这是 JavaScript 的历史行为。
✅ 正确的做法
方法一:使用箭头函数包装
js
const result = ['1', '2', '3'].map(str => parseInt(str, 10));
console.log(result); // [1, 2, 3]
方法二:使用 Number
构造函数(推荐)
js
const result = ['1', '2', '3'].map(Number);
console.log(result); // [1, 2, 3]
Number
更安全、语义清晰,且不会受第二个参数影响。
📌 总结
要点 | 说明 |
---|---|
map() 返回新数组 |
不改变原数组,符合函数式编程原则 |
回调函数参数 | (element, index, array) |
parseInt 陷阱 |
map 会把 index 传给 parseInt 作为 radix ,导致错误解析 |
安全转换建议 | 使用 Number() 或显式指定进制 parseInt(str, 10) |
🎯 最佳实践
- 避免直接将多参数函数作为
map
的回调。 - 使用箭头函数明确控制参数传递。
- 字符串转数字优先考虑
Number()
,除非需要特定进制解析。
掌握 map()
的原理和常见陷阱,能让你写出更健壮、可维护的前端代码。希望这篇文章帮你避开了那个经典的"坑"!