目录
一、什么是隐式转换?
定义:由编译器自动完成类型转换的方式就称为隐式转换。
二、转换规则
2.1 基本数据类型
2.1.1将值转为字符串
字符串连接符+
使用这一规则。(只要+
两边出现了字符串就是字符串连接符。)
编译器将非string类型的值转为string类型,然后再将其拼接成一个新的字符串。
const test = 1 + '0' + true + undefined + null;
console.log(test); // 10trueundefinednull
console.log(typeof test); // string
2.1.2将值转为数字(Number()函数)
自增/自减运算符,算数运算符,关系运算符使用这一规则。
下表列出将其他类型的值转换为数字的情况:
序号 | 其他类型 | 转换为number类型后的值 |
---|---|---|
1 | undefined | NaN |
2 | null | 0 |
3 | boolean | true 转为1,false 转为0 |
4 | string | left-aligned 空字符串'' ,"" 转为0,123 转为数值123,hello 和a123 转为NaN |
这里对关系运算符中的几种情况进行说明:
(1)字符串与字符串比较
比较方法(> < >= <= !=):通过依次比较字符串中每个字符所对应的unicode的值,若比较过程中能得出结果,直接返回结果并且不再比较后面的字符。
通过字符串的charCodeAt()
方法可以查看每个字符的unicode。
该方法的用法及细节请参考链接: MDN > String.prototype.charCodeAt()
- 例1
console.log('a2c' > 'ab3'); // false
// 分析
console.log('a2c'.charCodeAt()); // 97
console.log('ab3'.charCodeAt()); // 97
// 不能得出结果,继续比较
console.log('a2c'.charCodeAt(1)); // 50
console.log('ab3'.charCodeAt(1)); // 98
// 得出结果不再比较
- 例2
// 字符串比较1
console.log('bA'>'b'); // true
// 字符串比较2
console.log('bA'<'b'); // false
// 分析
console.log('bA'.charCodeAt()); // 98
console.log('b'.charCodeAt()); // 98
// 不能得出结果
console.log('bA'.charCodeAt(1)); // 65
console.log('b'.charCodeAt(1)); // NaN
console.log('b'.charCodeAt()); // 98
这里可以看出,当比较的字符串长度不同,并且公共长度的字符比较不能得出结果时,比较的是字符串的长度,来得出结果的。(个人推测,若观点有误,请指正!)
比较方法(==):只有两个相同的字符串比较才为true。
(2)null 与undefined
序号 | 关系式 | 结果 |
---|---|---|
1 | undefined == undefined ; | true |
2 | null== null; | true |
3 | undefined == null; | true |
Javascript规范中:规定
null
和undefined
是相等的。null
和undefined
都代表着无效的值。
(3)NaN
NaN
代表非数值的特殊值,用于指示某个值不是数字。NaN
与任何类型的值比较都是false。
2.1.3将值转为布尔值(Boolean()函数)
逻辑非运算符!
使用这一规则。编译器通过Boolean()
函数将非布尔类型的值转为布尔值。
下表列出只需记住以下转为布尔值为false的5种情况即可,其余全为true:
序号 | 值 | 备注 |
---|---|---|
1 | undefined | undefined 类型 |
2 | null | null 类型 |
3 | 0 | number 类型 |
4 | NaN | number 类型 |
5 | 空字符串:双引号"" 或单引号'' | 空格' ' ," " 为true |
2.2 引用数据类型
2.2.1 引用数据类型互相比较
比较的是引用数据类型指向的地址。
console.log([] == []);// false:两个空数组指向不同的地址
const a = [];
const b = a;
console.log(a == b); // true:数组a, 数组b指向相同的地址
2.2.2 引用数据类型与基本数据类型比较
引用数据类型都是object实例,都会继承object的方法,所以都有valueOf()
和toString()
方法。
转换规则:先使用valueOf()
获取原始值,如果原始值不是number类型,使用toString()转换为string类型,再转换为number
类型比较或计算。
引用数据类型的valueOf()
转换
引用数据类型 | 使用valueOf() 转换成原始值 |
---|---|
Number | number 类型。转换的值参考本文2.1.2将值转为数字 |
String | string 类型。转换为字符串。 |
Boolean | boolean 类型。转换的值参考本文2.1.3将值转为布尔值 |
Date | number 类型。转换为从 1970 年 1 月 1 日午夜开始计算的毫秒数。 |
Array, Math,RegExp, Function,Object | this,对象本身 |
常见内置对象的toString()
转换规则
常见内置对象 | 使用toString() 转换成字符串 |
---|---|
Array | 数组元素以逗号隔开的字符串 |
Function | 函数源代码的字符串 |
Object | [object Object] |
Math | [object Math] |
RegExp | 正则表达式的字符串值 |
常见内置对象的toString()
转换测试
console.log([1, 2, 3, 4].toString()); // 1,2,3,4
console.log({ age: 18 }.toString()); // [object Object]
function func() { }
console.log(func.toString()); // function func() { }
console.log(Math.toString()); // [object Math]
const exp = new RegExp(',');
console.log(exp.toString()); // /,/
2.3 特殊1:逻辑非与关系运算符同时出现
逻辑非!
的优先级高于关系运算符,所以优先转换为boolean类型,再进行关系比较。
例题:
console.log([] == !{}); // true
- 过程分析:
- 运算优先级:
!
>==
,!{}
即false
, 等式变为[] == false
[]
通过valueOf()
转换为[]
=>通过toString()
转换为''
,等式变为'' == false
- 将其转换为number类型,即:
0 == 0
,等式成立,结果为true
- 运算优先级:
2.4特殊2:+
陷阱
2.4.1字符串连接符(有时会被浏览器认为一元+
运算)
(1)字符串与其他类型拼接不再赘述。
(2)在浏览器的控制台中直接打印:空对象+其他数据类型时
空对象 + 任意对象(不同浏览器出现不同结果)
- Chrome
- 每个
{}
都会按照valueOf -> toString
的转换顺序变为字符串的[object Object]
+
两边出现了字符串,即为字符串拼接符。即:{} + {} -> '[object Object]' + '[object Object]' = '[object Object][object Object]'
- 每个
- FireFox
- 浏览器会将{}认为是一个空的代码区块(而不是一个对象字面量)并忽略,即:
+{}
- 一元
+
会触发强制类型转换。即:{} + {} -> +{} -> Number({}) = NaN
- 浏览器会将{}认为是一个空的代码区块(而不是一个对象字面量)并忽略,即:
空对象 + 其他数据类型(对象类型除外)
这次所有的浏览器都会将{}认为是一个空的代码区块,即使用一元
+
将其他类型转换为number类型的值。
Chrome
FireFox
2.4.2加法运算
除string类型与引用数据类型之外的原始类型的才是加法运算
核心:将其他原始类型转换为number
类型
console.log(1 + 1); // 2
console.log(1 + true); // 2
console.log(1 + null); // 1
console.log(1 + undefined); // NaN
console.log(true + null); // 1
console.log(true + undefined); // NaN
console.log(null + undefined); // NaN
总结
JS隐式转换规则以流程图形式呈现(字符串拼接符的隐式转换除外)