2

基本上所有的语言都有 隐式类型转换 ,但是对于 弱类型语言(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 与其他类型的对比

首先我们要明白 Booleantruefalse 的概念是什么

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

undefinednull 在相等的对比中是比较特别的,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)>>的内容,有兴趣的可以买来看一下,物超所值

SzHeJason
141 声望4 粉丝