JS 中的类型转换无论是我们在开发中还是在面试中都是经常遇到的。在正文开始之前先给大家看一道腾讯的面试题,你看看你能拿几分
js
//下面表达式的值是什么?
0 == "0";
0 == "";
2 == true;
2 == false;
false == "false";
false == undefined;
false == "0";
false == null;
null == undefined;
` \t\r\n ` == 0;
这种题目如果你掌握了 JS 的类型转换和运算符规则,那么你就能轻松拿满分,否则你连及格都很难做到。看完本篇文章之后,再回头看这个面试题或者其它关于类型转换及运算符的题目相信你都能够轻松应对
类型转换规则
JS 中类型转换规则分为四种
- 原始转数字
- 原始转字符串
- 所有转 bool
- 对象转原始
很多时候 JS 中数据类型的相互转换通常是隐式的,但也可以使用特定的方法进行显式转换。
比如运算符中任何值和字符串+时,都会先转换为字符串,然后再和字符串做拼接操作
js
console.log(1 + "23");
这种就叫隐士类型转换,当然隐士类型转换的情况还有很多,这里只是举了个例子
如果我们想将一个类型强行转换为另一种类型可以使用特定的方法,比如转成数字Number(xx)
,转成字符串String(xxx)
等等
原始类型转数字
先看一下原始类型转数字
js
//布尔值转数字
Number(true); //1
Number(false); //0
//null转数字
Number(null); //0
//undefined转数字
Number(undefined); //NaN
//string转数字
//1.空字符串转数字(包括空白字符-空格换行等)都是0
Number(""); //0
Number(" "); //0
Number(" \n\r\t "); //0
//2.包含数字的字符串,不是纯数字字符串就返回NaN,
Number("123"); //123
Number("123a"); //NaN
Number(" 123 "); //123
Number("12 3"); //NaN
原始转字符串
原始类型转字符串其实很简单,加引号就行了
js
String(true); //'true'
String(1); //'1'
String(null); //'null'
String(true); //'true'
所有转 bool
所有值转 bool 我们只需要知道为 false 的情况就行了,那么什么情况下是 false 呢?
js
//null转bool
Boolean(null); //false
//undefined转bool
Boolean(undefined); //false
//0
Boolean(0); //false
//空串,如果是空白字符串会被转成true
Boolean(""); //false
//NaN
Boolean(NaN); //false
除了这些之外都会转成 true
对象转原始
对象转原始类型首先这个对象会先调用valueOf()
方法,如果得到的不是原始类型还是一个对象的话就会调用toString()
方法再进行转换,比如想把一个对象转成数字Number({})
,它会返回什么?
根据上面的解释可以知道,首先会先调用这个对象的
valueOf()
得到的还是{}
,然后就会调用toString()
方法得到'[object Object]'
字符串,然后将其转换成数字类型得到的就是NaN
。
js
let obj = {};
Number(obj); //1
如果我们让一个对象的valueOf()
方法返回一个数字类型,结果就会变成数字,比如
js
let obj = {
valueOf() {
return 1;
},
};
Number(obj); //1
因为此时对象调用 valueOf 得到了一个原始类型就不再调用 toString 方法了而是直接进行转换了
ok,现在我们虽然已经知道了数据类型的转换规则,回头看开始的那些面试题还是一脸懵逼是不是?
因为我们还需要掌握 JS 种的运算规则
运算规则
我们需要掌握运算规则有哪些?如下所示
算术运算: = - * / % ++ --
比较运算: == > < >= <= != === !==
逻辑运算: ! && || ?: ??
下面我们一一了解它们的运算规则
算术运算
首先是算术运算,它的规则有以下 3 种
- 非原始类型会先转成原始类型再参与运算
- 原始类型转换成数字类型然后运算
- 如果参与运算的有一个字符串则都转成字符串拼接
需要注意的是NaN 与任何类型值运算得到的都是 NaN
举个例子undefined+null
它的结果是什么?
是不是感觉很简单,首先
undefined
转成数字是NaN
,null
转成数字是0
,而 NaN 与任何类型值运算得到的都是 NaN,所有结果就是 NaN
再比如true+null
的结果是 1;false+null
的结果是 0 等等
看一个经典的面试题[]+{}
它的结果是什么?
我们来分析一下:
两个都不是原始类型,首先需要先转为原始类型,根据对象转原始可以知道,
[]
转为原始类型会先调用valueOf()
方法得到的还是[]
,再调用toString()
方法得到的是''
,而{}
上面已经说过会变成'[object Object]'
,因此转换后的运算就是''+'[object Object]'
得到的结果就是'[object Object]'
比较运算
比较运算的规则分为几种,首先我们先看下> < >= <=
- 非原始类型会先转成原始类型再比较
- 原始类型转成数字类型比较
- 两边都是字符串则比较字典顺序
注意:NaN 和任何数据类型比较返回的都是 false
比如
js
"b" > "a"; //true
true > null; //true
true > undefined; //false undefined会转成NaN
true < undefined; //false
再看一下==
,双等号是我们遇见比较多的运算符,也是情况比较多的
- 两端如果只有一端为非原始类型,非原始类型先转成原始类型再比较
- 类型相同直接比较值
- 两端都是原始类型转成数字比较
- undefined 和 null 只有相互比较或者与自身比较才会为 true
注意:两端只要有一个 NaN,那么结果就是 false,NaN==NaN 也是 false
看到这里开头那个面试题就迎刃而解了,你想错一个都难
js
//下面表达式的值是什么?
0 == "0"; //true 右端会转数字 0==0
0 == ""; //true 右端会转数字 0==0
2 == true; //false 右端会转数字 2==1
2 == false; //false 右端会转数字 2==1
false == "false"; //false 两端转数字 0==NaN
false == undefined; //false undefined 和 null 只有相互比较或者与自身比较才会为 true
false == "0"; //true 两端转数字 0==0
false == null; //false undefined 和 null 只有相互比较...
null == undefined; //true undefined 和 null 只有相互比较...
` \t\r\n ` == 0; //true 左端转数字 0==0 空字符串转数字(包括空白字符-空格换行等)都是0
然后再看一下 ===
或者!==
,这两个其实没什么好说的,只有值和类型都一样才会返回 true 或者 false
最后看一下逻辑运算符! && ||
,它们运算规则首先会将值转为布尔然后再进行运算
首先是非运算符!
规则
- 它可以将值转化为布尔型
- 返回相反的值
所以说有时候两个非运算!!
可以用来将某个值转换为布尔型类型
js
!true; //false
!"123"; //false
!!null; //false
再看下与&&
运算符的规则
- 从左到右将操作数转为布尔值
- 如果转换的布尔值为 false 则停止操作并返回这个值的原始值
- 如果没有转换布尔值为 false 的值,则返回最后一个值
总结就是: 与运算返回第一个假值,如果没有假值就返回最后一个值
js
1 && 2; //2
0 && 2; //0
1 && "" && 2; //''
然后是或||
运算符规则,和与&&
运算符相反,它是寻找真值
- 从左到右将操作数转为布尔值
- 如果转换的布尔值为 true 则停止操作并返回这个值的原始值
- 如果没有转换布尔值为 true 的值,则返回最后一个值
总结就是: 或运算返回第一个真值,如果没有真值就返回最后一个值
js
0 || 2; //2
"" || "哈哈"; //哈哈
0 || "" || null; //null
与之类似的还有空值合并??
运算符,它和||
运算符不同的是相对于它的假值只有undefined
和null
总结就是: ??
运算符返回第一个真值(除了undefined
和null
都是真值)如果没有真值就返回最后一个值
js
0 ?? 2; //0
null ?? ""; //''
null ?? undefined ?? null; //null
最后就是三元运算符?:
,这个很好理解,?
前是条件,条件为真返回:
前的值,否则返回:
后的值 condition ? expr1 : expr2
js
2 > 1 ? "a" : "b"; //a
到这里关于数据转换和运算符规则基本就讲完了,你是不是有种豁然开朗的感觉! 以后无论是工作还是面试再遇到此类问题相信你肯定能轻松应对了。如果感觉本篇文章对你有所帮助的话,彦祖们还不点个赞吗~