可以分为4大类:
奇葩NaN
NaN是一种奇葩的number,究竟有多奇葩呢?和自己各种不等够不够!
number中还有一个比较特殊的东西Infinity。用typeof查看可知Infinity属于number型。
浮点数计算精度
javascript的世界中对整数和小数一视同仁都看作双精度浮点数2^64位。
0.1+0.2 !== 0.3:0.1和0.2会先被转成二进制再相加最后转成十进制,因为浮点型不能准确表示0.1和0.2(一直持续着没有尽头),所以得到的结果也就不是0.3了。
9999999999999999:number型最大安全值为9007199254740991,2^53-1
还有一道额外的题~
parseInt会先将第一个参数转成字符串String(),再对此字符串进行int转换。图中0.000000008被字符串化的时候会先转换成科学记数法,即8e-9,再对"8e-9"进行int转换时将指取到8(因为后面的e不是数字)。
奇葩的Math
Math.max()和Math.min():为什么前者为-Infinity,后者为Infinity呢?怎么想都觉得非人类啊!其实我们可以这样考虑,每一个Math.max(a)隐含的参数是-Infinity,相当于Math.max(a,-Infinity),这样无论a为什么它永远都比-Infinity大,这也就是为什么Math.max(5)=5会返回它自身了。
"+"二元操作符
[]+{}:首先明确数组也是对象,其次明确"+"这个表达式是需要左右两边的操作数都必须转换为原始值的。类型转换会先判断是否为原始值(基本类型),如果是引用类型会调用valueOf()看是否返回原始值,如果不返回原始值,会再去调用toString()。[]会先调用valueOf(),但返回的是他本身[]不是原始值,于是调用toString(),得到“”空字符串。{}会通过toString()得到“[object Object]”,所以最终结果是“”+“[object Object]”=“[object Object]”
[]+[]:即""+""="",非常easy~
{}+[]:{}既可以被理解为复合语句块也可以被理解为对象或者函数声明的时候,javascript会将其直接理解成复合语句块。{}+[]=>{};+[]忽略前面得到+[],此处"+"表达式并不代表加法的二元运算符,它是一元运算符(因为前面没有操作数了),作用是将后面的操作数转化为数字,于是""被转换成数字0。
{}+{}:同理,前面的忽略,直接理解成+{},但“[object Object]”无法转换成数字,因此得到NaN。
先明确true == 1;false == 0
true+3:"+"一边是boolean,一边是number时会先将boolean的值转成number型。结果为4。
true+true:"+"两边都是boolean时,会先将两边的值转成number型。结果为2。
true+"4":"+"一边是boolean,一边是字符串时会先将boolean的值转成字符串。结果为true4。
-'69'+69:"-"一元操作符会先将'69'转化为number型,即-69+69,结果为0;
写在最后:感觉==和===终于搞懂之后又跑出来一堆一元运算符和二元运算符来恶心人~
那么最恶心没有之一的!+[]+[]+![]闪亮登场,我们一个一个来判断。
!+[]:首先+一元操作符将后面的操作数转化成number型也就是0;其次!一元操作符将后面的操作数转化成boolean型,因为是逻辑非运算,所以!0=true;结果是true。
!+[]+[]:第二个+是二元运算符,它左边是boolean型true,右边是string型"",所以连接起来是"true"。
!+[]+[]+![]:最后![]为false,第三个+是二元运算符,它左边是string型"true",右边是boolean型false。所以最终结果为"truefalse"。