javascript中神奇的隐式转换

最常见的==和!=造成的隐式转换,网上已经有很多人总结了,总结起来就一张图:

ObjectStringNumberBoolean

不同类型之间做==或!=运算,会按箭头方向转换直到类型相等。
(undefined, null和NaN后面再细说)


下面是重点,到底哪些运算会造成隐式转换呢?
按照我的理解,除了===和!==比较运算,其他所有的运算都会造成隐式转换。
JS的运算符可以归纳为7大类:
1. 算术运算符
2. 赋值运算符
3. 比较运算符
4. 逻辑运算符
5. 三元运算符
6. 位运算符
7. 字符串连接运算符
我们来逐个验证。

1.算术运算符

+, -, *, /, %, ++, –

转换规则1:所有类型均转换为Number;
转换规则2:null会转换为0,undefined会转换为NaN

   console.log(null + 1);     //1    +运算符作为字符串连接符的例子请看第7条
   console.log(undefined - 1);     // NaN
   console.log([] * 1);    //0    []先转换为String:'',再转换为0
   console.log([1] / 1);    //1    [1]先转换为String:'1',再转换为1
   console.log({} % 1);    //NaN    {}先转换为String:'[object Object]',再转换为NaN: 
   var a = true;  console.log(++a);    //2    不能写成++true, ++运算只能作用于变量
   var a = false; console.log(--a);    //-1

2.赋值运算符

=,+=,-=,*=,/=,%=

赋值运算的隐式转换与算术运算同理,这里就不再验证了。

3.比较运算符

==, !=, >, >=, <, <=(不讨论绝对等于)

转换规则1:若均为基本类型,不需转换;若均为复杂类型,做>和<比较需转换为String再比较;
转换规则2:若类型不同,按照最上图进行转换,直到类型相等,最终转换为String或Number;
比较规则1:Number直接比较;String逐字符比较他们的unicode值;复杂类型比较引用的对象是否相同。
比较规则2:NaN既不等于任何值,也不大于和小于任何值;
比较规则3:undefined == null 返回true,两者和除此之外所有类型都不相等。

console.log('true' == true);    //false    均转换为Number,既 NaN == 1
console.log([] != true);    //true    均转换为Number,既 0 != 1
console.log('a' > 1);    //false    均转换为Number,既NaN>1
console.log('a' > '1');    //true    直接比较unicode值

4.三元运算符

a ? b : c

转换规则1:第一个值会转换为Boolean;
转换规则2: 空字符串/0/null/NaN/undefined会转换为false,其他为true

console.log( [] ? 1 : 2);    //1

5.逻辑运算符

&&, ||, !

&& 和 || 转换规则:所有类型均先转换为Boolean做运算,再根据各自运算规则返回其中的一个原值;
! 转换规则:所有类型均转换为Boolean,并返回该Boolean的取反

console.log(undefined && 1);    //undefined
console.log({} || 'a');    //Object {}
console.log(!undefined);    //true

6.位运算符

~, &, |, ^, <<, >>, >>>

转换规则1:所有类型均转换为Number;
转换规则2:NaN, null和undefined都会转换为0(注意,与算术运算符不同)

console.log(~undefined);    //-1
console.log('25'&[3]);    //1
console.log({}|NaN);    //0
console.log({}^[1]);    //1
console.log(NaN<<1);    //0
console.log({}>>1);    //0
console.log(['6.6']>>>0);    //6

7.字符串连接运算符

+

转换规则:若运算符前后有一个为复杂类型或String类型,两者均转换为String类型

console.log(null+[]+1);    //null1

这么多的隐式转换,简直是防不胜防。
那么为什么只有==这个运算的隐式转换这么受人关注呢?

一个原因是,其他运算符造成的隐式转换就是我们想要的,比如算术运算符我们就是想得到Number,但是==运算不同,它的隐式转换并不可控,出的意外更多;
另一个原因是,我们完全可以用===来避免这种隐式转换,而其他的运算符就没有这种待遇了。

猜你喜欢

转载自blog.csdn.net/shengandshu/article/details/71601514