前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于数字的前端面试题

关于数字的前端面试题

作者头像
用户1687375
发布2018-06-08 12:21:42
1.4K0
发布2018-06-08 12:21:42
举报
文章被收录于专栏:较真的前端

写在前面,总结面试题不一定是为了准备面试,更是对于自己的一种温故知新,了解自己知识的熟练度和理解度。

问题一览

  1. 如何判断一个值是否为NaN?运行环境内建的方法isNaN()有坑
  2. 如何判断两个浮点数相等?如fn(0.1+0.2 , 0.3) => { /*返回true*/}
  3. 如何检测一个值是否整数?
  4. 对于一个数字进行取整,你能说出多少种方法?
  5. 当一个变量显式类型转换时(利用Number()方法),遵循的规则是什么?
  6. Number([])和Number([1,2,3])的值分别是什么?说明其原理?
  7. 讲一讲parseInt()方法遵循的运算规则?

问题解答

1.如何判断一个变量是否为NaN?

相信大多数人应该都会想到这个不就用运行环境提供的内建方法 isNaN()来判断吗?

如下面的代码:

事实上,isNaN的逻辑是“输入参数是否不是NaN,也不是数字”。这句话是在《你不知道的JavaScript(中卷)》 2.4.3中提到的,我理解isNaN()的逻辑可以理解为“输入参数是否可以转化为数字”更加贴切和容易理解。所以字符串“666”的返回值为true,因为他可以转化为数字,而字符串“what?”不能转换为数字,故返回值为false。

那既然无法用isNaN来检测一个值是否为NaN,那么该如何做?

有两种办法

第一种,根据上面的实验,我们可以先判断输入参数的类型是否为number,再调用isNaN方法,这样就避免了对于非数字类型的判断错误。代码如下:

第二种,利用NaN的一个特性,它是JS语言中唯一一个不等于他本身的值,所以我们也可以这么写。

还有一种,可以利用ES6中提供的Object.is()方法来进行验证

如果你的代码中仍然使用isNaN(),那么你的程序迟早会出现bug。

2.如何判断两个浮点数相等?

在JavaScript中,0.1+0.2 不等于0.3是一个经典问题,他时刻提醒你,对于浮点数来说,他并不能像普通数学题那样简单比较。究其原因,是因为在JS中,0.1+0.2的值是一个比较接近0.30000000000000004的数字,所以他并不等于0.3。

不要小看这个问题,浮点数的运算经常会出现,比如计算商品的折扣、计算税费等情况下都需要对浮点数进行运算。

通常的做法是设置一个误差范围值,通常称为“机器密度”,对于JavaScript来说,这个值是2的-52次幂,即Math.pow(2, -52)。

所以,可以对于浮点数进行比较时可以用下面的方法(在ES6中,Number.EPSILON是自带的),以下代码示例来源于《你不知道的JavaScript(中卷)》2.3.2

此外,需要说明的是JavaScript中最大的浮点数是Number.MAX_VALUE和Number.MIN_VALUE。

3.如何检测一个值是否整数

如果允许使用ES6的话,可以用Number.isInterger();这个方法干净利落。

如果不允许使用ES6的话,可以自行写一个pollyFill方法。

4.对于一个数字进行取整,你能说出多少种方法?

parseInt()这个方法你肯定能想到。但你可能想不到他的坑还真不少,未必是无懈可击的方法。

在最后一个问题中,我在详细解答。

其实还有很多很简单有效的方法来对数字进行取整。

比如下面的方法:

这三种方法都是可以的,分别说一下:

8.84|0或者 写成0 | 8.84 都是一样的,从语法上看,他是让0与指定值进行按位“或”运算,在JavaScript中,它先对指定值执行了ToInt32的转换,在按位进行或运算,所以最终结果就是把指定值转换为32位的整数。

而~~8.84也是对变量进行ToInt32的转换;再进行一步按位“取非”运算,即对每个字节进行反转;然后,再对结果再次“取非”。

那么8.84>>0的操作就同理可证了……

但是,上面的三种方法也是有其局限性的,因为他们是遵循ToInt32的转化规范,所以他们也只能对于32位的数字进行转换,所以再加上一个符号位,那么他们所能处理的数字范围在2的正负31次幂之间,即-2147483648 ≤ x ≤ 2147483647。

5.当一个变量显式类型转换时(利用Number()方法),遵循的规则是什么?

这个问题应该会有很多种文法,比如,把一个字符串转换为数字时,都经历了哪些操作?

这道题还是很考验基础的,一般工程师是不会记住这个细节点的。

言归正传,ES5规范中规定了这个抽象操作ToNumber。

对于布尔型:true的结果为1,false的结果为0;

对于undefined: 结果为NaN

对于null:结果为0

对于字符串类型:遵循数字常量的相关规则和语法。处理失败时会返回NaN。

对于复杂类型:会先调用该值得valueOf()方法,如果有并且返回基本类型之,就是用该值进行强制类型转换。如果没有就是使用toString()的返回来进行强制类型转换。

举个例子来加强一下记忆:

6.Number([])和Number([1,2,3])的值分别是什么?说明其原理?

这道题应该也算是上一道题的加强记忆了。

大家已经知道了是先调用valueOf(),再调用toString()方法,那么空数组和[1,2,3]有什么区别呢?

因为数字的valueOf()方法返回的是数组本身,不是一个基本类型,所以还会调用toString()方法;而数组的toString()方法返回的是数组各项通过逗号拼接一起的字符串(可以理解调用了Array.prototype.join(",")方法),所以空数组返回空字符串,转换为数组自然就是0;而数组[1,2,3]则只能转换为NaN了.

那么,大家觉得下面的代码应该输出什么呢?为什么?

7.讲一讲parseInt()方法遵循的运算规则?

之前已经提到了,parseInt()方法含有太多坑。也许面试者会问你下面的代码为什么可以输出52

如果想回答上面的问题,你必须知道下面的知识点。

parseInt(string, radix);方法的接受两个参数:

  • string:

要被解析的值。如果参数不是一个字符串,则将其转换为字符串(使用 ToString 抽象操作)。字符串开头的空白符将会被忽略。

  • radix:

一个介于2和36之间的整数(数学系统的基础),表示上述字符串的基数。比如参数"10"表示使用我们通常使用的十进制数值系统。始终指定此参数可以消除阅读该代码时的困惑并且保证转换结果可预测。当未指定基数时,不同的实现会产生不同的结果,通常将值默认为10。

返回值:

返回解析后的整数值。 如果被解析参数的第一个字符无法被转化成数值类型,则返回 NaN。

如果 parseInt 遇到了不属于radix参数所指定的基数中的字符那么该字符和其后的字符都将被忽略。接着返回已经解析的整数部分。

所以,这里就明白为什么字符串'52px'会被parseInt()解析为52,因为没有传递第二个参数radix,所以默认按照10进制进行解析,而字符'p'不在10进制内,所以字符'p'和后面的字符全部被忽略,直接返回数字52.

下面是parseInt()最经典的一个坑:

如果不亲自一试,你绝不会相信上面代码的输出是18。

这里需要知道的是,1/0运算结果是“无穷”,在JavaScript中为Infinity,而这个Infinity转换为字符串则为'Infinity',第一个字符是'I',在以19为基数时他的值为18。第二个字符‘n’不是一个有效的数字字符,所以除第一个字符外,后面的字符全部被忽略,所以最后就返回了18。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-11-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 较真的前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档