基本上所有的语言都有 隐式类型转换
,但是对于 弱类型语言(JS)
来说 ,隐式类型转换会比 强类型语言(Java)
带来更大的副作用,有些行为甚至是不可思议的。虽然你可能很惊讶 ,甚至可能怀疑是 JS 的 BUG,但是这都是有 JS 语言自己的一个隐式类型转换的套路。
基本的隐式类型转换
基本类型的隐式转换
这个其实我们使用的最多,例如 "10" + 1
结果返回的是 101
而不是 11,这就是String
类型的隐式转换。
在+号的左右侧,只要又有一个或者两个操作数是字符串则做拼接操作
但是其实这句话并不完全对,例如[1,2] + [3,4]
这种也会发生字符串拼接,至于为什么会拼接,我后面会提到,这里就先卖个关子。
还有 if、while等
表达式里面会将值强行转换成Boolean
,-
运算符会将左右两边换成 Number
这些都是基本类型的隐式转换,由于都比较熟了,加上例子太多我就不一一写出来了
复杂类型的隐式转化
上面提到的都是基本类型和基本类型的隐式转换,那么复杂类型是如何进行隐式转换的呢?
复杂类型的转换会把自身变成基本类型,其方法就是调用 ToPrimitive
,实际上就是去尝试使用 valueOf()
和toString()
获取一个基本类型,优先使用 valueOf
如果无法获取到基本类型,则使用 toString
。如果两者都没有获取到基本类型,他会抛出一个 Cannot convert object to primitive value
错误.
现在我们看回上面提到的 [1,2] + [3,4]
实际上就是 "1,2" + "3,4"
结果自然等于 1,23,4
相等比较的隐式类型转换
在开始讲解 相等比较的隐式类型转换
的之前,我写几个行代码,大家看看下面这些代码会打出什么类型.
false == "";
true == "why?";
false == "0";
"" == 0;
[] == 0;
[] == false;
[] == ![];
[] == "";
[1,2,3] == "123";
[1,2,3] == "1,2,3";
let a = null,b;
a == b;
a == false;
b == false;
a == "";
b == "";
a == 0;
b == 0;
大家可以执行一下代码,看看结果是不是与你预期的一样。我估计能答对的人不会很多。我用一个一个案例来讲明 JS的隐式类型转换
Number 与其他类型的对比
假设 X 是
Number
类型,Y 是其他类型,则 X == Y 实际上是 X == Number(Y)
显示转化Number的时候,""和空格会被转换为0
"" == 0 ----> Number("") == 0 ----> 0 == 0
Boolean 与其他类型的对比
首先我们要明白 Boolean
中 true
和 false
的概念是什么
false
的取值范围是 undefined、null、false、+0、-0、 NaN、""。true
的取值范围为 除了false
意外的所有 情况
然后就是在 Boolean
和其他类型相等比较 的时候,会遵循下面的一条规则
假设 X 是
Boolean
类型,Y 是其他类型,则 X == Y 实际上是 Number(X) == Y
我们按着这个规则去看上面的实例
false == "" ----> 0 == ""
而刚刚我们在上面说过 0 == ""
结果为 true
true == "why?" ----> 0 == "why?" ----> 0 == Number("why?") ----> 0 == NaN
结果为 false
至于 false == "0"
我就不解释了,一样的转换逻辑
特别的 undefined 和 null
undefined
和 null
在相等的对比中是比较特别的,JS 规范中
在相等比较中 null 和 undefined 是同一个概念 也就是 null == undefined 为 true,除此之外他与任何东西都不想等
let a = null,b;
a == b; //true
//下面这些全部返回false
a == 0;
b == 0;
a == "";
b == "";
a == false;
b == false;
关于复杂类型的相等比较
复杂类型的想等比较涉及上面讲的ToPrimitive
,其规则就是
假设 X 是
复杂类型
类型,Y 是其他类型,则 X == Y 实际上是 ToPrimitive(X) == Y
[] == 0; // "" == 0
[] == false; // "" == false
[] == ""; // "" == ""
[] == ![] // [] == false
[1,2,3] == "123"; // "1,2,3" == "123"
[1,2,3] == "1,2,3"; // "1,2,3" == "1,2,3"
一些特别的情况
-
NaN
与自身不想等
NaN
与自身不想等是 JS
一直以来的规范,至于有啥设计原因,我暂时不清楚,有了解的读者可以告诉我下
本书引用了一些<<你不知道的JavaScript(2)>>的内容,有兴趣的可以买来看一下,物超所值