一、前言
面试题:[1,2,3].map(parseInt)输出结果是什么
二、两个方法
由本题引申出两个js方法的细节,分别是数组map方法和parseInt方法,两个熟悉到不能在熟悉的方法,放在一起却翻了船
1. map
函数说明:
map方法会给原数组中的每个元素都按顺序调用一次 callback 函数。callback 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。
函数签名
var newArr = arr.map(function(currentValue, index, arr) {
// each item will processed by this function
}, thisArg)
参数说明
该方法有两个参数,第一个是回调函数,第二个在回调函数中this的指向
第一个参数回调函数接受三个参数,第一个是当前正在遍历的数组元素(必须),第二个参数是当前元素的索引值(非必须),第三个元素是数组本身(非必须)(引用)
第二个参数是thisArg,用于指定回调函数中this的指向(上下文环境)
注意点:
-
map会自动传递三个参数,分别是当前正在遍历数组元素,当前元素索引,数组本身
-
map函数不是原地算法,必须用一个新数组接受map方法的返回值
-
map遍历的数组在调用时就已经确定,即使在回调函数中增加或者减少数组项,也不会影响遍历次数。如果增加元素不会遍历到
let arr = [1, 2, 3, 4, 5, 6];
let res = arr.map((item, index, ref) => {
ref.push(1);
return item;
})
console.log(res); // 1,2,3,4,5,6
如果删除元素,则遍历的时候会访问不了元素
let arr = [1, 2, 3, 4, 5, 6];
let res = arr.map((item, index, ref) => {
ref.splice(0,1);
return item;
})
console.log(res); // 1,3,5,empty,empty,empty
- 如果回调函数中没有返回, 则默认值为undefined
2. parseInt
函数说明
根据指定进制解析字符串,并返回十进制表示的整数
函数签名
function parseInt(str, radix) {}
参数说明
两个参数,第一个是要解析的值(必须),如果不是字符串会调用toString方法转换字符串
第二个参数是使用什么进制(非必须),默认不是 十进制
,范围为2-36
默认不是十进制
是引用的MDN文档,刚看到其实有点疑问,为什么不是十进制,我日常用这个方法,都不会指定第二个参数(进制数),解析也都是用的十进制。
看过后面的解析渐渐明白,默认确实不是十进制,而是根据你要解析的字符串确定的,具体解释如下
如果没有传进制,主要分两情况
- 如果要解析的字符串以
0x
或者0X
开头,则以16进制进行解析 - 如果要解析的字符串以
0
开头,则以八进制或者十进制进行解析,在ECMAScript5中指明要以十进制进行解析,但浏览器兼容存在问题,最好指定第二个参数 - 其余情况默认按照十进制解析
如果传递了第二个参数
- 如果第二个参数为
undefined
,0
,null
则以十进制进行解析 - 如果进制数小于
2
或大于36
,则返回NaN
解析过程如下图
这里的第一步,也就是先尝试解析第一个参数这一步是我自己的理解,没有看过源码,感觉这样可能比较合理,先考虑边界情况。
注意
- 在解析过程中,如果遇到字符串不属于指定进制中的数字,则解析终止,只返回已解析的部分
parseInt("123a",10) // 遇到a,解析停止,返回123
parseInt("123a123",10) // 遇到a,解析停止,后面部分不会解析,返回123
- 在转换bigInt的时候可能会出现精度丢失的问题,因为bigInt最后会有一个n的拖尾,在解析时被丢失
- parseInt可以理解正负号,如果待解析字符串带有符号,则会记录符号,并从非符号位开始解析
三、解析
题目[1,2,3].map(parseInt)
根据map特性 map会自动传入三个参数
,代码其实本来面目是这样
[1,2,3].map(function(item, index, arr){
return parseInt(item, index, arr);
})
逐个解析,执行三次循环,过程应该是这样
- 第一次循环
parseInt(1, 0, [1,2,3])
第三个参数被忽略,要解析的字符串为数字1,先调用toString转字符串,第二个参数为0,根据解析规则,应该按照十进制进行解析,所以结果为1,见parseInt参数说明第三条
2. 第二次循环
parseInt(2, 1, [1,2,3])
基本同上,第二个参数为1,直接返回NaN,见parseInt参数说明第四条
3. 第三次循环
parseInt(3, 2, [1,2,3])
超出二进制能表示的范围,第一位数字无法解析,返回NaN,见parseInt参数说明第四条
综上,返回结果为【1,NaN,NaN】