你不行还是JavaScript不行
2018-12-06 本文已影响0人
菜鸟很浮夸
遇见了很多次,有些人在js里遇到自己想不通的问题就抱怨js是垃圾的情况。我觉得探究一下为什么比骂街好很多。
0.1 + 0.2 != 0.3
与几乎所有的脚本语言一样,js数字类型是基于IEEE 754标准来实现的,使用 “双精度” 格式,即64位二进制;更多关于 的请看这里 ;
简单来说:
- js的数值只用64bit来表示
- 0.1 和 0.2 这些十进制小数用二进制表示是一个无限小数(只有可以x/2^n的小数,即分母是2的倍数的小数能精确表示)
- js会舍弃多余的部分,取一个近似值。所以小数的近似值计算反而更常见
-
0.1 + 0.2 = 0.30000000000000004
, js不能把它看成 0.3,当然也就有了0.1 + 0.2 != 0.3
parseInt(0.0000001) == 1 而 parseInt(0.000001) == 0
parseInt
在js中本来就比较奇葩,但是,这种用法也比较奇葩;
关于parseInt
简单的特点如下:
- 作用:解析数字字符串
- 从左到右解析,遇到非数字字符就停止
- 第二个参数指定进制
- 如果没有第二个参数,小心八进制和16进制(如果第一个字符是X,x转换为十六进制,如果是0转换为八进制)
- 传一个非字符串会先转换为字符串
具体到标题的问题:0.0000001
被转换成字符串时变成 "1e-7"
,parseInt
不识别科学计数法, 不过parseFloat
可以识别科学计数法。
一切皆对象
首先这是不对的;
基本类型没有.length
和 .toString()
类似的方法,当需要的时候,js会自动为基本类型包装一个封装对象,那些属性和方法实际是通过这个封装对象来访问的。
[] == ![]
结果是 true
, 这个结果之所以让很多人感到意外,因为,一种错误的直觉:==
比较会先吧两边的值转换为布尔值,然后进行比较,事情没那么简单:
-
先将右边的
[]
,转换为布尔,然后取“非” -
所有对象都是真值,所以
![]
转换为false
;此时式子:[] == false
-
==
两边类型不同,发生强制类型转换 -
转换的大概规则是:
- 最终比较的是基本类型值
- 引用类型值会通过
ToPrimitive
操作,转换为基本类型值 - 最最后会转换为相同类型值比较或数值和数值的比较(而不是布尔值和布尔值比较)
-
[]
通过ToPrimitive
操作(此处实际执行的toSring()方法)得到空字符串 -
false
会通过ToNumber
转换为 0, 此时式子:"" == 0
-
==
两边类型不同,发生强制类型转换,把 空串 转换为0
-
0 == 0
结果为true
ToPrimitive
参考: