前言
昨天在朋友圈看到了这张有趣的图
那我们今天就来讲讲这个图吧
正文
Typeof
1 | typeof NaN |
因为typeof
只能返回下面的东西
所以它只能返回个number
了,而且NaN
一般是在想把什么东西转化成number
类型但是转化失败了才会出现的结果,某种意义上还是说的过去的
浮点数精度
1 | 9999999999999999 // 10000000000000000 |
JavaScript 中的数字按照 IEEE 754 的标准,使用 64 位双精度浮点型来表示,而我们知道,想用有限的位来表示无穷的数字,显然是不可能的,因此会出现一些列精度问题:
- 浮点数精度问题,比如
0.1 + 0.2 !== 0.3
- 大数精度问题,比如
9999 9999 9999 9999 == 1000 0000 0000 0000 1
- toFixed 四舍五入结果不准确,比如
1.335.toFixed(2) == 1.33
有三种思路来解决这个问题
- 考虑到每次浮点数运算的偏差非常小(其实不然),可以对结果进行指定精度的四舍五入,比如可以
parseFloat(result.toFixed(12))
; - 将浮点数转为整数运算,再对结果做除法。比如0.1 + 0.2,可以转化为
(1*2)/3
。 - 把浮点数转化为字符串,模拟实际运算的过程。
不过其实只有第三种是完全可行的
先来看第一种方案,在大多数情况下,它可以得到正确结果,但是对一些极端情况,toFixed 到 12 是不够的,比如:
1 | 210000 * 10000 * 1000 * 8.2 // 17219999999999.998 |
第二种方案也有一些问题,并不是完全可行
1 | // 这两个浮点数,转化为整数之后,相乘的结果已经超过了 MAX_SAFE_INTEGER |
所以,最终考虑使用第三种方案,目前已经有了很多较为成熟的库
这些库不仅解决了浮点数的运算精度问题,还支持了大数运算,并且修复了原生toFixed结果不准确的问题。
Math.max和Math.min
问就是看文档,其实没啥好记的,当成特殊情况下了解一下就可以了
奇怪的 + - !
1 | [] + [] // "" |
这是把+
丢到一个表达式前面会发送的事情
简单来说就是会调用Number()
把表单式转化为number
类型
这是传统意义上的+
会发生的过程
翻译一下
- 把左右两边转化成原始类型
- 如果一边是字符串,把另一边转成字符串做拼接
- 否则把两边都转成数字进行
+
运算
这是把-
丢到一个表达式前面会发送的事情
简单来说就是调用Number()
转成数字然后取反(正负的反)
这是传统意义上的-
会发生的过程
翻译一下:把两边都转成数字进行运算
然后这是!
会发生的
简单来说就是调用Boolean()
然后取反
顺带一提,这个表达式,你以为是对象加数组
1 | {} + [] |
其实是这样的
1 | {} |
上面的对象会被解析成一个代码块,然后只剩下+[]
,而Number([])
的结果就是0
再顺带一提,这个东西
1 | (!+[]+[]+![]).length |
运行起来其实是这样的
1 | (!+[] + [] + ![]).length |
== 和 ===
==
看这篇:https://www.sakura-snow.com/archives/142
===
就是在==
的基础上不进行类型转化而已,类型不一样直接返回false