隐式类型转换

转载自:隐式类型转换

一、隐式转换规则

  • 转成string类型:+(字符串连接符)
  • 转成number类型:++ –(自增自减)、+ - * / %(算术运算符)、> < >= <= == != === !==(关系运算符)
  • 转成boolean类型:!(逻辑非)

二、字符串连接符与算术运算符规则混淆

说明

  • +两边只要有一边是字符串,+就是字符串连接符
  • +两边都是数字,+就是算术运算符
    规则
    1、字符串连接符+:会把其他数据类型调用String()方法转成字符串然后进行拼接。
    2、算术运算符+:会把其他数据类型调用Number()方法转成数字然后做加法计算。
    举例
    1
    2
    3
    4
    5
    6
    7
    8
    //+是字符串连接符: String(1) + 'true' = '1true'
    console.log(1+ "true"); //1true
    //+是算术运算符:1 + Number(true) = 1 + 1 = 2
    console.log(1+true); //2
    //+是算术运算符:1 + Number(undefined) = 1 + NaN = NaN
    console.log(1+undefined); //NaN
    //+是算术运算符:1 + Number(null) = 1 + 0 = 1
    console.log(1+null); //1

三、关系运算符会把其他数据类型转成number之后再比较关系

规则
1、当关系运算符两边有一边是字符串时,会将其他数据类型使用Number()转换,然后比较关系。
2、当关系运算符两边都是字符串时,将两边字符串对应位置上的字符从左到右依次转成unicode编码进行比较。
举例

1
2
3
4
5
6
7
8
console.log('2' > 10); //false
console.log('2' > '10'); //true
console.log('abc' > 'aad'): //true
console.log(NaN == NaN); //false
console.log(undefined == undefined); //true
console.log(null == null); //true
console.log(undefined == null); //true
console.log(undefined === null); //false

四、复杂数据类型在隐式转换时会先转成String,然后再转成Number运算

规则
1、先使用valueOf()方法获取其原始值,如果原始值不是number类型,则使用toString()方法转成string,再将string转成number运算
举例

1
2
3
4
5
6
7
8
9
//先将左边数组转成string,因为右边也是string,则两边对应位置转成unicode编码进行比较
//(1) [1.2].valueOf(); => [1,2] 原始值不是number类型
//(2) [1.2].toString(); => '1,2'
console.log([1,2] == '1,2'); => //true
var a = {};
//(1) a.valueOf(); => {} 原始值不是number类型
//(2) a.toString(); => '[object Object]'
console.log(a == '[object Object]'); //true

看个问题,如何完善a,使其打印出’yes’?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//问题
var a = ???
if(a == 1 && a == 2 && a == 3){
console.log('yes');
}
//分析:逻辑与运算,一假则假,要想if分支语句小括号条件成立,则必须要让a的值同事等于1 且等于2 且等于3。乍看之下,好像根本不可能实现,但是复杂数据类型会先调用valueOf()方法,然后转成number运算,而对象的valueOf()方法是可以重写的。
var a = {
i: 0,
valueOf: function () {
return ++a.i;
}
}
或者
a = {
value: [3,2,1],
valueOf: function () {
return this.value.pop();
}
}

五、逻辑非隐式转换与关系运算符隐式转换

说明
空数组的toString()方法会得到空字符串,而空对象的toString()方法会得到字符串[object Object]
规则
1、关系运算符:将其他数据类型转成数字
2、逻辑非:将其他数据类型使用Boolean()转乘布尔类型
3、以下8种情况转换为布尔类型会得到false
0、-0、NaN、undefined、null、’’(空字符串)、false、document.all()
除以上8种情况之外,所有数据都会得到true。
举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//(1) [].valueOf().toString() ''
//(2) Number('') => 0
console.log([] == 0); => //true
//逻辑非的优先级高于 ==
//(1) ![] false
//(2) false == 0
console.log(![] == 0); //true
//本质上是空对象 {} 与 !{} 做比较
//(1) {}.valueOf().toString() => '[object Object]'
//(2) !{} => false
//(3) Number('[object Object]') == Number(false)
console.log({} == !{}); //false
//引用类型数据存在堆中,栈中存储的是地址
console.log({} == {}); //false
console.log([] == []); //false
//(1) [].valueOf().toString(); => ''
//(2) ![] => false
//Number('') == Number(false)
console.log([] == ![]); //true