类型转换
js中,涉及类型转换主要有以下几种:
if()
将内容转换为布尔值,为false的值包括:false undefined null ‘’ 0 NaN
!
把值转换成布尔值,为true的值包括:0 null undefined NaN '' false,其他的均为false(可能有纰漏,没找到什么统计文章)
+(加) -(减)符号
具有将值转换为数值类型,会将类型转换为number
console.log(typeof +'a'); // number
console.log(1+ +'123'); // 124,先将'123'转换为数值,再执行相加
运算符: +、-、*、/、%、++(递加)、--(递减)
在js中,当运算符在运算时,如果两边数据不统一,CPU就无法计算,这时我们编译器会自动将运算符两边的数据做一个数据类型转换,转成一样的数据类型再计算
这里先列一下各种值在Number()执行后的结果,下面需要用到(当然底层实现并不完全是通过Number来判断的,否则1+{}就不会是1[object Object]了)
Number([]); // 0
Number(''); // 0
Number(null); // 0
Number(false); // 0
Number('1'); // 1
Number(Infinity); // Infinity
Number('1a'); // NaN
Number(undefined); // NaN
可以稍微总结一下(或许有纰漏):
空数组、空字符串、null、false转换为数值为0
纯数字字符串可以转换为数值,否则为NaN
infinite转换为数值为infinite
其他的基本为NaN(如上所说,可能有纰漏,所以用词:基本)
除了+号,其他运算符都是直接将非数值类型转换为数值运算
而+号有两个功能:运算 / 字符串拼接(如果有一方为字符串,则会变为字符串拼接)
运算,可以分为以下两类:
- 数字和非字符串相加
1+null; // 1
1+undefined; // NaN
1+{}; // 1[object Object],具体原因往下看
- 非数字相加
true+true; // 1
true+{}; // true[object Object]
上面内容也可以看到,{}使用Number()会返回NaN,但是在+号运算符下他却变成[object Object]的字符串类型
这是因为对象中有两个方法 valueOf() 和 toString(),在运算时,先执行valueOf方法,如果结果不是原始数据类型,那么会继续执行toString方法,如果还不是原始数据类型,那么就会抛出错误。
ES6新增[Symbol.toPrimitive],对象被转为原始类型的值时,会调用[Symbol.toPrimitive]方法,返回该对象对应的原始类型值。
可以通过以下改写方法来测试一下执行结果
let obj = {
valueOf () {
return 200; // 对象的valueOf会返回自身,所以这里改回{},就会输出300
},
toString() {
return 300;
}
}
console.log(true+obj);
所以总结起来,对于转换为数值类型,底层原理就是:先将非数值类型值调用valueOf方法,如果返回的不是基本类型值,继续调用toString方法
Q:为什么1/{}结果会是NaN,1+{}会是1[object Object],能解释出来了吗?
A:因为对象转换为基本类型值是'[object Object]',所以1/一个字符串,结果返回NaN,而+号具有字符串拼接的功能,所以1+{}返回1[object Object]
比较运算: > == <
- 字符串比较,比较的是ascii码
console.log('a' < 'bbb'); // true,比较左右两边首字母ascii码
console.log('a'.charCodeAt(0)); // 97
console.log('b'.charCodeAt(0)); // 98
- 数值和字符串比较,规则同运算符,看能否转换为数值,如果为NaN则结果为false
console.log(1 < 'aaa'); // false,因为aaa转换为数值为NaN
console.log(1 < '123'); // true
- ==
先说一下一些比较的规则:
- 对象与对象比较,比较的是命名空间
{} == {}; // false
- NaN和任何类型比较都不相等,包括它自身
NaN == NaN; // false
- 如果有Boolean类型,会把Boolean转换为数字
1 == true; // true
- 对象 和 字符串/数字/symbol比较,会把对象转换为原始数据类型
{} == '[object Object]; // true
Q: [] == ![],结果是什么?能否解释一下?
A: true,首先有!
,单目运算符优先级最高,所以会先将![]
转换为布尔值,结果为false,false为布尔值,布尔值转换为数字,结果为0,所以到这里结果变成 [] == 0
,对象与数字比较,会将数字转换为原始类型,所以比较结果变成 '' == 0
,空字符串转换为0,所以结果为true
下一篇加深的文章:数据类型的细节知识,配合阅读,效果更佳
拓展阅读:
js面试题大坑——隐式类型转换
https://github.com/jawil/blog/issues/1
toString方法和valueOf方法以及Symbol.toPrimitive方法的学习