前言
在JavaScript中,类型转换有着非常重要的作用,它可以帮助我们将一种数据类型转换为另一种数据类型,从而更好地处理和操作数据。并且,类型转换还可以帮助我们在不同的数据类型之间进行比较和运算,从而提高程序的灵活性和可维护性。
类型转换也是面试中经常被问到的问题,因为它涉及到 JavaScript 的基础知识和核心概念,能够很好地检验应聘者对 JavaScript 的理解和掌握程度。
显式类型转换
人为使用类型转换方式将一种数据类型转换为另一种数据类型。
转换为数值类型
通过调用Number()
函数将特定的值转换成数值。
javascript
console.log(Number(undefined))//NaN
console.log(Number(null))//0
console.log(Number(true))//1
console.log(Number(false))//0
console.log(Number(0))//0
console.log(Number('abc'))//NaN
console.log(Number('123'))//123
console.log(Number(''))//0
console.log(Number('123abc'))//NaN
console.log(Number(' '))//0
console.log(Number(' 1 2'))//NaN
- null转数值:参数为
nll
时,结果为0。 - undefined转数值:参数为
undefined
时,结果为NaN。 - 数值转数值:结果为原数值。
- 字符串转数值:
- 如果参数为空字符串或是只有空格,结果为0;
- 如果参数是由
'数值'
组成的字符串(如'-12'、'1.25'、'-0.123'等),结果为该字符串相应的数值; - 除了上两种情况,其余字符串转数值的结果都为NaN。
- 布尔值转数值:如果参数是true,结果为1;如果参数是false,结果为0。
- 对象转数值:下文详细描述。
我们总结到一张表上:
null | undefined | 数值 | 空字符串或只有空格的字符串 | 由'数值' 组成的字符串 |
其余字符串 | true | false | |
---|---|---|---|---|---|---|---|---|
number | 0 | NaN | 原数值 | 0 | 对应的数值 | NaN | 1 | 0 |
转换为字符串类型
通过调用String()
函数将特定的值转换成字符串。
javascript
console.log(String(null));//'null'
console.log(String(undefined));//'undefined'
console.log(String(true));//'true'
console.log(String(false));//'false'
console.log(String(0.123)); //'0.123'
console.log(String(-0.123));//'-0.123'
console.log(String(123));//'123'
- null转字符串:参数为
nll
时,结果为'null'。 - undefined转字符串:参数为
undefined
时,结果为'undefined'。 - 数值转字符串:参数为数值,结果为'数值'。
- 字符串转字符串:参数为字符串,结果为原字符串。
- 布尔值转字符串:如果参数是true,结果为'true';如果参数是false,结果为'false'。
- 对象转字符串:下文详细描述。
我们总结到一张表上:
null | undefined | 数值 | 字符串 | true | false | |
---|---|---|---|---|---|---|
string | 'null' | 'undefined' | '数值' | 字符串 | 'true' | 'false' |
转换为布尔值类型
通过调用Boolean()
函数将特定的值转换成布尔值。
JavaScript
console.log(Boolean(1));//true
console.log(Boolean(-1));//true
console.log(Boolean(0));//false
console.log(Boolean(NaN));//false
console.log(Boolean(''));//false
console.log(Boolean('a'));//true
console.log(Boolean(undefined));//false
console.log(Boolean(null));//false
- null转布尔值:参数为
nll
时,结果为false。 - undefined转布尔值:参数为
undefined
时,结果为false。 - 数值转布尔值:如果参数为-0、+0或NaN时,结果为false;否则结果为true。
- 字符串转布尔值:如果参数为空字符串,结果为false;否则结果为true。
- 对象转布尔值:参数是对象,结果为true。
- 布尔值转布尔值:参数是布尔值,结果为传入的参数。
我们总结到一张表上:
null | undefined | -0、+0或NaN | 除-0、0和NaN外的数字 | 空字符串 | 除了空字符串 | 对象 | true | false | |
---|---|---|---|---|---|---|---|---|---|
boolean | false | false | false | true | false | true | true | true | false |
原始值转对象
原始值可以通过构造函数包装成对应的对象类型。
javascript
console.log(typeof (new String('abc')));//object
console.log(typeof (new Number(123)));//object
console.log(typeof (new Boolean(true)));//object
console.log(typeof (new Boolean(false)));//object
由于null
和undefined
没有对应的构造函数,所有没有办法通过该方法转为对象。
我们直接上表:
字符串 | 数值 | true | false | |
---|---|---|---|---|
object | new String(字符串) | new Number(数值) | new Boolean(true) | new Boolean(false) |
隐式类型转换
不是人为对数据类型进行转换,而是在编译器或运行环境自动进行的类型转换。
对象转原始值类型
将对象转换为原始值类型,通常是通过抽象操作ToPrimitive
完成的。
valueOf
valueOf()
用于返回对象的原始值,但是valueOf()
只适用于原始值的封装对象。当原始值的封装对象调用valueOf()
,返回这个原始值的封装对象的原始值。
toString
toString()
方法用于返回对象的字符串表示形式,但是不同的对象调用toString()
会有不一样的效果:
- 对于原始值的封装对象:调用
toString()
返回该原始值的字符串形式。 - 对于数组:调用
toString()
返回一个由数组元素组成的逗号分隔的字符串。 - 对于普通对象:调用
toString()
返回一个"[object Object]"的字符串。
ToPrimitive
为什么要突然聊起了toString()
和valueOf()
,当然是为了给主角ToPrimitive()
做铺垫。
ToPrimitive
有两个参数,一个是要转换的值(input),一个是期待返回的基本类型(默认为number
)。
ToPrimitive
的具体执行过程:
- 如果input不是对象类型而是原始类型,就直接返回该原始类型。
- 如果input是对象类型,并且期待返回的基本类型是
string
:- 首先调用对象的
toString()
,如果返回的结果是原始值就返回该原始值。 - 如果没有
toString()
方法或调用对象的toString()
返回的结果不是原始值,尝试调用valueOf()
,如果返回的结果是原始值就返回该原始值。 - 调用
valueOf()
返回的结果也不是原始值,则抛出错误。
- 首先调用对象的
- 如果input是对象类型,并且期待返回的基本类型是
number
:- 首先调用对象的
valueOf()
,如果返回的结果是原始值,则对该原始值进行转换为number后返回。 - 如果没有
valueOf()
方法或调用对象的valueOf()
返回的结果不是原始值,尝试调用toString()
,如果返回的结果是原始值,则对该原始值进行转换为number后返回。 - 调用
toString()
返回的结果也不是原始值,则抛出错误。
- 首先调用对象的
- 如果没有指定期待返回的数据类型就默认为
number
;如果input是Date
对象,则期待返回的数据类型会被设置为string
。
对象转布尔类型
当对象需要被转换为布尔类型时,几乎所有的对象都会被转换为true
。
eg:
javascript
if([]){
console.log('执行了')
}
if语句内部代码会执行吗?
当然会呀,因为数组转布尔值为true
。
一元操作符(+)
+
作为一元操作符,它会尝试将后面的值进行数值转换。
eg1:
javascript
let str = '123'
console.log(+str);//123
具体流程:
- JavaScript引擎识别到
+
是一个前置的运算符。 - 接下来,引擎会检查
+
操作符后面的操作数的类型。 - 因为
+
用于数值操作,引擎会尝试将+
操作符后面的操作数转换为数值。(该过程相当于调用了Number()
构造函数)
eg2:
javascript
let obj = {}
console.log(+obj);//NaN
具体流程:
- JavaScript引擎识别到
+
是一个前置的运算符。 - 接下来,引擎会检查
+
操作符后面的操作数的类型。 - 因为
+
用于数值操作,引擎会尝试将+
操作符后面的操作数转换为数值。- 将
{}
转换为数值会调用ToPrimitive
方法,没有特别指定期待转的基本类型默认为number
。 - 首先调用
valueOf
方法,空对象{}
没有定义自己的valueOf()
方法,所以它继承自Object.prototype.valueOf()
,这个方法对于普通对象而言返回对象本身,依然是对象,并非原始值。 - 因为
valueOf()
没有给出一个原始值,ToPrimitive
会尝试调用对象的toString()
方法,给到的结果是"[object Object]"
字符串,转换为数值为NaN
。
- 将
eg3:
javascript
let arr = []
console.log(+arr)
输出结果是什么呢?你来试试吧。
二元操作符(+)
+
作为二元操作符,它会根据操作数的类型执行不同的操作。eg:左操作数+右操作数:
- 分别对左操作数和右操作数调用
ToPrimitive
转换为原始值类型。- 如果左操作数和右操作数中有一个是字符串,那么就将左操作数和右操作数都转换为字符串进行拼接。
- 如果左操作数和右操作数都不是字符串,就将左操作数和右操作数都转换为数值进行相加。
eg:
javascript
console.log({} + [])//'[object Object]' + '' ---> '[object Object]'
相等操作符(==)
在比较x==y
时,有以下的执行方式:
- 如果x和y的类型相同:
- undefined==undefined--->true
- null==null--->true
- number==number进行下一步判断:
- NaN==NaN-->false
- 相同的值==相同的值-->true
- +0==-0-->true
- 其余都是false
- string==string
- 相同字符串==相同字符串-->true
- 否则为fasle
- boolean==boolean
- true==true-->true
- false==false->true
- 否则为false
- 如果x和y类型不同:
- null==undefined-->true
- 如果x和y中有对象,则对该对象调用
ToPrimitive()
转换为原始值进行比较。 - 如果x和y中有布尔和字符串都转换为数值进行比较。
这是官方文档的介绍,可以参考一下。
严格相等操作符(===)
提到==
,一定会联想到===
。
严格相等操作符 ===
:
- 不进行类型转换 :
===
在比较前不进行任何类型转换。如果两个操作数的类型不同,直接判定它们不相等。 - 比较规则:只有在两个操作数的类型和值都完全相等时,才认为它们相等。