神秘行为:
老规矩,还是我们先来看看前置知识
阅读本文您将收获
- js Number 的科学计数法
- parseInt、Number.prototype.toString方法
科学记数法
先借用一下百度百科的解释
科学记数法是一种记数的方法。把一个数表示成a与10的n次幂相乘的形式(1≤|a|<10,a不为分数形式,n为整数),这种记数法叫做科学记数法。
例如:19971400000000=1.99714×10^13。
计算器或电脑表达10的幂是一般是用E或e,也就是1.99714E13=19971400000000。
js在何时会使用科学记数法呢?
在 ECMAScript 规范中 Number.prototype.toString 方法和 Number.prototype.toPrecision 方法中都有提到当 Number 被转化为 String 时,满足以下条件将会被处理为科学记数法(the code unit 0x0065 (LATIN SMALL LETTER E)),感兴趣可以去看一下。
- 当一个 数字number 被转为为科学记数法后,number = a*E^n 满足
n <= -6或者21 < n时,会将结果转换为科学记数法的字符串表达式
规范中还有一个用来计算 n 的比较复杂算法,原谅我太菜了没有看懂,如果有能看懂的还请在评论区指导一下
也就是说
-
如果一个数字为小数,且整数部分为0,且小数点后6位为0,那么将被转化为科学记数法
-
如果一个数字的整数部分 大于21 位,那么将被转化为科学记数法
我们来看几个例子
通过前面 a==1 && a==2? 看看ECMAScript规范里面自动类型转换都有啥! 和 让人头疼的隐式转换?必然也有迹可循。 两篇文章我们已经知道 String 方法会自动为我们调用参数的 toString 方法。
console.log((1.0000001).toString()) // 1.0000001
console.log(String(1.0000001)) // 1.0000001
console.log(String(0.1111111)) // 0.1111111
console.log(String(0.0000001)) // 1e-7
console.log(String(0.00000000002)) // 2e-11
console.log(String(123456789012345678901)) // 123456789012345680000
console.log(String(1234567890123456789012)) // 1.2345678901234568e+21
console.log(String(1234567890123456789012.1)) // 1.2345678901234568e+21
parseInt 方法
262.ecma-international.org/11.0/#sec-p…
依然是看看ECMAScript 对该方法的定义,这里我只贴了与本文相关的部分,有兴趣可以去看看。
parseInt (
string,radix)parseInt函数生成一个整数值,该整数值由根据指定 radix 解释 string 参数的内容决定。忽略 string 中的前导空格。如果 radix 未定义或为0,则假定为10,除非数字以0x或0x开头,在这种情况下,假定 radix 为16。如果 radix 为16,则数字也可以选择以0x或0x开头。
Let
inputStringbe ? ToString(string).注意: parseInt只能将 string 的前导部分解释为整数值;它忽略任何不能被解释为整数表示法一部分的代码单元,并且没有给出任何此类代码单元被忽略的指示。
可以看出 parseInt 做的第一件事就是先将 string 参数转化为 String 类型的值,这点很重要。
我们来看看几个例子
parseInt("123") // 123
parseInt("123aaa") // 123
parseInt("1a23aaa") // 1
parseInt("a1a23aaa") // NaN
parseInt(123) // 123
parseInt(4564563) // 4564563
进入正题
有了上面 科学计数法 和 parseInt 方法的介绍。我们其实很容易就能想到 parseInt(0.0000005) === 5 的现象。我们来看一下执行过程。
parseInt(0.0000005)
首先 parseInt 方法会将参数转化为 String 类型, 我们的参数是 Number 类型, 所以将其转化为 Strng 类型会调用 Number.prototype.toString 方法。效果如下
parseInt(String(0.0000005))
上面我们已经找到, 当调用 Number.prototype.toString 方法时, 如果其值的科学计算法 a*10^n 满足 n <= -6 或者 21 < n, 就被被转化为科学记数法。
很明显 0.0000005 转化为科学计数法为 5*10^-6 , 满足转化为科学计数法表达式的条件,所以代码的效果就变成了这样。
// String(0.0000005) = "5e-6", 这个在上面介绍 Number.prototype.toString 时已经介绍过了
parseInt("5e-6")
而 parseInt("5e-6") 的结果为 5, 这就可以解释为什么 parseInt(0.0000005) === 5 了。
总结
-
当调用 Number.prototype.toString 方法时, 如果其值的科学计数法 a*10^n 满足
n <= -6或者21 < n, 就被被转化为科学计数法。-
如果一个数字为小数,且整数部分为0,且小数点后6位为0,那么将被转化为科学计数法。
-
如果一个数字的整数部分 大于21 位,那么将被转化为科学计数法。
-
-
parseInt 方法会先将参数转化为字符串再执行操作。