Fork me on GitHub

隐式类型转换

你可能见到过这样的情况:”5” - 3 == 2和”5” + 3 == “53”,可是这是为什么呢?

上节提到过关于强制类型转换到的概念,通过调用方法来实现数据在不同类型间的转换。同样的,既然有强制类型转换,那么也会有隐式类型转换。

隐式类型转换

转换为数字类型进行比较运算。以下几种情况会有数据的默认转换:

isNaN()

翻译过来意思就是:是NaN吗?此方法会先调用Number()的方法将数据转化为数字类型来进行比较。

数字类型包括四个值:具体的数字,NaN,Infinity,-Infinity

如果转换为数字时,返回的值刚好是NaN,则调用isNaN()时返回true。

具体步骤为:isNaN(demo) => Number(demo) => NaN => true / false

1
2
3
4
isNaN(23)       //false
isNaN('a') //true
isNaN(NaN) //true
isNaN(null) //false

当调用Number()数据是怎么转换的,可以参考上一篇(强制类型转换)。Number(null)值为0

++/- -, +/-

++ / - - 分为前置++和后置++,区别在于变量的输出顺序不同。
+/- 为一元正负运算符,并不是通常所说的数学中的加和减。即+4, -3

1
2
3
+3      //3
-5 //-5
+'a' //NaN
1
2
var str = 'a';
console.log(str ++); //NaN

算数运算符

‘+ , - , * , / , % (取余) ‘会将符号两边的值转换为数字进行运算

1
2
3
4
5
6
null + 1    //1
"abc" + 1 //"abc1"
"2" * "a" //NaN
8 - "2" //6
5 / "3" //1.6666666666666667
5 % "3" //2

需要注意的是: + 号遇到字符串时,相当于字符串的拼接,他会把加号另外一边不是字符串的值转化为字符串,并和已知的字符串进行拼接。

如果没有字符串时,则将 + 两边的值正常转换为数字类型来进行计算。

1
2
3
2 + ""      //"2"
2 + " " //"2 "
2 + "5" //"25"

空串””和空格字符串” “的区别在于其布尔值,空串””为false,空格字符串” “为true

逻辑运算符

‘ &&(与) , ||(或) , !(非) ‘输出运算结果。运算结果为真实的值
(1) && (2):找到假为止。他会先取出(1)表达式的值,看是否为真。
(1)为真,继续执行(2),不管(2)结果为真还是为假都输出(2)表达式的运算结果。
(1)为假,输出(1)表达式的运算结果。

(1) || (2):找到真为止。他会先取出(1)表达式的值,看是否为真。
(1)为真,输出(1)表达式的运算结果。
(1)为假,继续执行(2),不管(2)结果为真还是为假都输出(2)表达式的运算结果。

!(1):取反。(1)运算结果为真时,取反则为假。(1)为假,取反为真。

1
2
3
1 && 2          //2
"a" || NaN //"a"
!4 //false

比较运算符

‘ > , < , >= , <= , == , != ‘比较结果为布尔值

1
2
3
4
5
6
1 == "1"                //true
"a" > "b" //false
0 == "" //true
0 == false //true
undefined == null //true
NaN == NaN //false

字符串和数字比较时,会将字符串转化为数字进行比较。字符串比较时,比较的为ASCII值。

根据undefined和null的特殊性质(undefined和null不等于0,不大于0,不小于0),所以让他们两个相等。

NaN不等于任何值,包括他自身。

不发生类型转换

===(绝对等于) , !==(绝对不等于)

1
2
1 == "1"    //true
1 === "1" //false

小练习

1
2
11 + "11"           //"1111"
undefined == NaN //false
1
2
3
4
5
6
7
var str = "abc";
str += 1; //"abc1"
var test = typeof(str); //"string"
if (test.length == 6) { //new String(str).length = 6; => delete
test.sign = "typeof的返回值可能为string"
}
console.log(test.sign); //undefined

包装类。强行给原始值加上某个属性时可以加上,但是实际访问时并不存在。所以if的条件并不成立,即不能给test加上sign属性。

1
2
3
4
5
var str = false + 1;        
console.log(str); //1

var demo = false == 1;
console.log(demo); //false

有赋值和比较运算符时,先比较后赋值。即false != 1, 比较运算符,输出结果为布尔值。

1
typeof typeof(undefined);       //"string"
1
2
3
if (typeof(a) && -true + (+undefined) + "") {
console.log("hello"); //hello
}

typeof(a)返回值为”undefined”,数据类型为字符串,为真。接着逻辑运算符后面的代码,-true + (+undefined) + “” => -1 + NaN + “” => NaN + “” => “NaN”,为字符串类型,为真,执行if里面的条件语句。

1
2
3
4
5
if (11 + "11" * 2 == 33) {
console.log("smile"); //smile
}

!!" " + !!"" - !!false || console.log('no'); //1 + 0 - 0 => 1
1
2
3
[3 < 1 < 2, 1 > 2 > 3];     //[true, false]

[3 < 1 < 2, 3 < 1 <= 0]; //[true, true]

当有多个比较运算符时,从左到右两个值一起进行比较,并将第一次比较的结果和第二次比较运算符右边的值作比较。

3 < 1 < 2比较时就是先让3和1比,3 > 1,所以第一个比较的结果返回false(0),然后再让0和后面的2比,0 < 2, 所以比较结果为真,返回true。

也就是3 < 1 < 2 => 0(false) < 2 => true