透过网红面试题,超详细解析 parseInt,学不懂找我

程序员成长指北

共 9545字,需浏览 20分钟

 ·

2021-08-10 06:23

点击上方 程序员成长指北,关注公众号

回复1,加入高级Node交流群

最近面试了几个前端开发,我都问了一道算是网红面试题,其中两个应届毕业生,两个两年开发经验的,他们都没有给到我想要的答案。

很多人可能觉得这种网红题目是在刁难人,没有实际的意义。但是在面试时,有时候想要快速了解一个人对某些知识的掌握,还是有意义的。而且说出答案是一回事,重点还在于他们得出答案的分析过程。

考察的点

console.log([1234].map(parseInt))

这道题考察的点:

  1. 对数组map方法的掌握
  2. parseInt函数的了解
  3. 考察对进制转化的掌握
  4. parseInt与parseFloat有何区别

废话不多说,直接上主菜~

console.log([1234].map(parseInt))
  • 输出结果:1,NaN, NaN, NaN

这个答案,很多人都是清楚的,接下来我的问题是,可以说一下map迭代的过程吗?

数组map方法

数组的map方法,是ES5中为数组定义的迭代方法,返回结果是一个新数组,其结果是该数组中的每一个元素调用一次提供的函数后的返回值:

语法:

var new_array = arr.map(function callback(currentValue[, index[, array]]{
 // 新数组的返回元素
}[, thisArg])

参数:

  • callback:数组迭代的每一项执行的回调函数,可以有三个参数:
    • currentValue:当前迭代项
    • index:当前迭代项的索引 (可选)
    • array: map 方法调用的数组(可选)
  • thisObject:在执行回调函数时定义的 this 对象(没有传递或者为 null,将会使用全局对象)。

我们简单温故了数组map方法, 接下来再详细的认识一下parseInt方法。

parseInt方法

不少人会觉得parseInt不就是将字符串转成一个整数吗, 平时经常使用。但是关于parseInt还真要仔细的说道说道,因为这里有些细节非常容易忽视。

语法

parseInt(string, radix);

返回值

从给定的字符串中解析出一个整数,或者NaN

关于返回NaN:

  • radix 小于 2 或大于 36
  • 第一个非空格字符不能转换为数字。

parseInt(string, radix) 解析一个字符串并返回指定基数的十进制整数, radix 是2-36之间的整数,表示被解析字符串的基数。

这是MDN给的解释,其实理解起来有点困难,这里我一步步的拆解一下。首先,解析一个字符串并返回指定基数的十进制整数这句话怎么理解呢?

parseInt 第一个参数理解

第一个参数是字符串?其实并不是...

是指将parseInt第一个参数字符串转为整数, 那如果传入的第一个参数不是字符串,如何处理呢, 这里就有一个转化规则(其实也是parseInt的一个小坑):

parseInt转化规则

  1. 如果第一个参数传入的不是字符串,首先会默认将传入的参数转为字符串(使用toString
  2. 从左边开始查找有效数字字符,转为数字;当遇到非有效数字字符,则停止查找

举几个例子:

parseInt(12); // 12
parseInt('20px'// 20
parseInt("p20")  //NaN

通过上面的代码,结合转化规则来看:

parseInt(12),首先是将数值12转为字符串'12', 然后再转为整数。

parseInt('20px'),从左边开始查找,当找到字符p时,发现是非有效字符,停止查找,对已找到的有效数字进行转换,所以结果是将字符串'20'转为整数。

parseInt("p20") ,当第一个字符不能转为数字,parseInt会返回NaN

parseInt 第二个参数理解

回到我们上边分析MDN的原话:解析一个字符串并返回指定基数的十进制整数, 这个还要注意指定基数, 就是parseInt(string,radix)的第二个参数「radix」,就是这个基数, 表示将第一个参数string当作radix进制。

这里有一个注意点,我发现有的人容易弄混:

parseInt是将radix进制的字符串转为十进制的整数(很多人弄混成:转成radix进制的整数)。

也就是说parseInt返回的的结果只能是十进制的整数或者NaN

那我们之前没有传第二个参数啊,是什么情况呢???

规则

  • radix如果为undefined、0或者未指定的:
    • 一般情况下,radix为10(十进制)
    • 如果string传入的是以0x(一个0,后面是小写或大写的X)开头, 那么radix就会被当作传入的为16, string就被的看作16进制去解析
  • radix是在2-36之间的整数,表示2-36进制; 如果不在2-36之间,最后返回结果都是NaN

同样举几个例子,结合规则看一下:

parseInt('0x11'// 17
parseInt('10'2)  // 1
parseInt('12'2)  // 1

我们简单分析一下上面的代码:parseInt('0x11')省略了radix参数,并且以0x开头,那么就将0x11看作16进制来解析,11转为十进制整数,结果为17(如果对进制转换不熟悉,后面有详细讲解)。

parseInt(10, 2), radix传入2,将'10'看作2进制,转换成十进制整数就是1。

parseInt('12', 2), 这个转换结果也为1, 这里又有一个坑需要注意,当解析到字符串'2'时,发现是非有效数字,(有的人可能会说:2怎么不是有效数字了!!),咳,这里要注意,我们是将'12'看作二进制的,二进制只有01,所以2当然不是有效数字, 将字符串'2'忽略,转换结果就是1。

通过上面的几个例子相信对parseInt有一定的了解,这里我要补充一点关于进制转换的知识,就当复习巩固了(因为面试时,我变更了一下题目的数值,发现有的人不会,或者说忘记了进制转换)

任意进制如何转十进制

二进制、八进制、十六进制等向十进制转换都是很容易的,就是按位相加,位指的是位权重(位上的数字乘以权重),权重就是N进制的第几位的位数见一次方。假如当前数字是N进制,那么:

  • 对于整数部分,从右往左看, 第i位的位权重为:
  • 对于小数部分,需要从左向右看,第m位的位权重为:

举几个例子看一下:

分别将下面的数字按要求转为十进制

FA1089  // 将16进制转为十进制
673.321 // 将8进制转为十进制
011001  // 将2进制转为十进制

FA1089 = + + + +   +

我将每一位的转换做了连线,方便理解,FA1089一共6位, 从右往左看,第一位9,位权重为: ,依次类推...需要注意的是: A~F对应的是十六进制的10-15

接下来看看一下八进制673.321的转换:

673.321 = + + + + +

image.png

二进制转十进制转换方式也是同理,这里就不赘述。

解题

前面对于数据遍历方法mapparseInt方法以及进制转换,铺垫了这么多, 接下来就来分析一下正题:

[1234].map(parseInt)

map迭代过程如下:

  1. parseInt(1, 0), 前面讲到 parseInt第二个参数不传、传的是0或者undefined,默认当做十进制处理, 输出结果为:1 ;
  2. parseInt(2, 1), 第二个参数为1, 不在2-36之间, 返回结果NaN;
  3. parseInt(3, 2), 将3作为二进制转换为十进制整数,但是二进制只有0和1,找二进制数字就什么都没有找到, 所以输出NaN ;
  4. parseInt(4, 3), 这里也是,4 不是3进制中数字, 输出结果NaN

这道题的答案就出来了: 1 NaN NaN NaN

拓展

parseInt还有一个兄弟方法parseFloat, 你知道他们的异同点吗,以及它们和Number有什么区别?

首先都知道parseIntparseFloat和Number都是将一个变量转换为数字类型。

parseInt 和 parseFloat 的区别:

  • parseFloat只能用于将字符串转换成10进制的浮点数,只接受一个参数,不能识别数据的原始进制,所有数据基数按10进制转换。
  • parseInt 将字符串转为10进制 整数,并且还支持第二个参数指定第一个参数的原始进制。

Number与parseInt的区别:

parseInt 处理机制:

  • parseInt如果处理的值是字符串,从字符串左侧开始查找,遇到非有效数字则停止查找(+-号除外);
  • 如果不是字符串,则先转为字符串,然后开始查找有效数字

注意:上边提到的有效数字,并不是数字都是有效数字, 而应该根据parseInt第二个参数指定的进制来看。比如指定的二进制, 那么2、3这样的数字就是非有效数字

Number处理机制:

  1. 如果是Boolean值,true和false将分别转换为1和0。
  2. 如果是数字值,只是简单的传入和返回。
  3. 如果是null值,返回 0。
  4. 如果是undefined,返回NaN。
  5. 如果是字符串,遵循下列规则:
    • 如果是字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即“1”变成1,“123”会变成123,而“011”会变成11(前导的零被忽略了);
    • 如果字符串中包含有效的浮点格式,如“1.1”,则将其转换为对应的浮点数值(同样也会忽略前导零);
    • 如果字符串中包含有效的十六进制格式,例如"0xf",则将其他转换为相同大小的十进制整数值;
    • 如果字符串是空的(不包含任何字符),则将其转换为0;
    • 如果字符串中包含除上述格式之外的字符,则将其他转换成NaN.
  6. 如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用的对象的toString()方法,然后再次依照前面的规则转换返回的字符串值。

温故知新

通过上面的学习, 通过一道练习题目,温习一下文章讲解的内容:

var arr = [10180104223]
arr = arr.map(parseInt)
console.log(arr) 

如果觉得这篇文章还不错
点击下面卡片关注我

来个【分享、点赞、在看】三连支持一下吧

   “分享、点赞在看” 支持一波 


浏览 11
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报