经常看到这个面试题:
- 为什么 [‘1’, ‘7’, ‘11’].map(parseInt) 返回 [1, NaN, 3] - 掘金
- Why [‘1’, ‘7’, ‘11’].map(parseInt) returns [1, NaN, 3] in Javascript
想必大家已经非常熟悉Map的原理,因为:
map(callback, [thisArg])
方法:
- 接受一个回调函数
callback
,返回一个新的数组
- 返回的数组的元素的值为调用
callback
函数所返回的值(原数组有几个元素,就调用几次callback
)callback
接受 3 个参数:
- currentValue:当前正在处理的数组元素的值
- index:当前正在处理的数组元素的索引
- arr:调用
map
方法的数组
而parseInt接收两个参数:string值和radix进制值:
- string:被解析的字符串(前后空格会被忽略,若不是字符串,则转换成字符串)
- radix:指定
string(第一个参数)
的基数(2~36,即2 进制
~36进制
),若不传或传0
,则string(第一个参数)
以10 进制
来解析
所以:
['1', '7', '11'].map(parseInt); => [1, NaN, 3]
// 第一次迭代: val = '1', index = 0, array = ['1', '7', '11']
parseInt('1', 0, ['1', '7', '11']); => 1 因为 radix 为 0 ,所以 string 按照 10 进制 处理,返回 10 进制数 1
// 第二次迭代: val = '7', index = 1, array = ['1', '7', '11']
parseInt('7', 1, ['1', '7', '11']); => NaN 因为 radix 为 1,不在 2~36 范围,直接返回 NaN
// 第三次迭代: val = '11', index = 2, array = ['1', '7', '11']
parseInt('11', 2, ['1', '7', '11']); => 3 因为 radix 为 2(二进制),所有 11 为3。
[1, NaN, 3]并不是我们预期的值,今天我们反其道而行,写一个unary一元函数,使[‘1’,‘7’,‘11’] map之后输出[1,7,11];
我们第一时间想到,只将回调函数的currentValue传去给parseInt方法:
['1','7','11'].map(function(currentValue,index,arr){
return parseInt(currentValue);
})
(3) [1, 7, 11]
为了通用性,写一个闭包函数,抽象出一个unary方法:
const unary = (fn)=> fn.length === 1 ? fn: (currentValue)=>fn(currentValue);
['1','7','11'].map(unary(parseInt))
参考资料