经常看到这个面试题:
为什么 ['1', '7', '11'].map(parseInt) 返回 [1, NaN, 3] - 掘金 https://juejin.im/post/5d0202da51882546dd10087b
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))
参考资料
JavaScript ES6 函数式编程入门经典 (web 开发经典丛书) - 码农电子书!
来源: http://www.mzh.ren/array-map-parseint-and-unary-function.html