JavaScript里的类型转换

120 阅读4分钟

今天我们讲一讲js里面的类型转换

首先思考一个问题,为什么 '1' === 1会返回false,而 '1' == 1会返回true呢?

 '1' === 1  

// false

 '1' == 1    

// true

原来在js中“===”表示全等,并不会进行隐式转换,它只负责判断值和类型是否相等;而“==”会进行隐式转换,只判断值是否相等。

转换分为隐式转换和显式转换。我们先来讲一讲显示转换。

一、显示类型转换

1.原始类型转换

(1)转布尔

在js中我们可以通过Boolean()将其他类型转为布尔类型。

console.log(Boolean());   // false

 console.log(Boolean(null));   // false

 console.log(Boolean(undefined));   // false

 console.log(Boolean(-100));   // true

 console.log(Boolean(0));       // false

 console.log(Boolean(NaN));    // false

 console.log(Boolean(''));     // false

 console.log(Boolean('aaa'));   // true

 console.log(Boolean(true));   // true

根据例子可以发现:

对于null,undefined返回false,

对于数字,0和NaN返回false,其余数字则返回true,

对于字符串,空字符串返回false,其余则返回true。

(2)转数字类型

在js中我们可以通过Number()将其他类型转为数字类型。

console.log(Number(true));   // 1

console.log(Number(false));   // 0

console.log(Number(null));     // 0

console.log(Number(undefined));   // NaN

console.log(Number(''));       // 0

console.log(Number('123'));     // 123

console.log(Number('1,2,3'));   // NaN

console.log(Number('abc'));     // NaN

根据例子可以发现:

对于null返回0,undefined返回NaN,

对于布尔类型,true返回1,false返回0,

对于字符串,空字符串返回0,对于可解析的数值返回其解析数值,对于含有无法解析值的字母和逗号等则返回NaN。

(3)转字符串

在js中我们可以通过String()将其他类型转为字符串类型。


console.log(String(undefined));   // 'undefined'

console.log(String(true));   // 'true'

console.log(String(false));   // 'false'

console.log(String(123));   // '123'

根据例子可以发现,字符串的转换就比较简单粗暴,不论传入什么,直接加上引号转成字符串。

2.对象的类型转化

当我们在类型转换的时候传入的不是原始类型,而是对象,那么js又该怎么去处理呢?

我们可以查阅官方文档分析其底层逻辑。

image.png

image.png

image.png

根据官方文档我们可以知道,如果是对象转成字符串,js的运行逻辑:

首先js会先交给内置函数ToString({})去处理,之后再交给内置函数ToPrimitive()去处理。如果发现是想转成字符串,则执行Toprimitive({},String),处理完成返回结果给ToString()

如果如果是对象转成数字,js的运行逻辑:

js会先交给内置函数ToNumber({})去处理,,之后再交给内置函数ToPrimitive()去处理。如果发现是想转成字符串,则执行Toprimitive({},Number),处理完成返回结果给ToNumber()

那么Toprimitive()的运行逻辑又是什么呢?我们再分析一下官方文档。

image.png

(1)对象转成字符串String(obj)  ||  Object.prototype.toString.(obj)

ToPrimitive(obj,String)

    - 如果obj是原始类型,则直接返回

    - 否则,调用obj.toString(),如果得到原始类型,则返回

        - 否则,调用obj.valueOf(),如果得到原始类型,则返回  

            - 否则,报错

所以我们知道对象转字符串实际执行以下几种操作:

    - {}.toString() 返回由 “[object”和class 和“]” 组成的字符串

    - [].toString() 返回由数组中元素用逗号拼接组成的字符串

    - xx.toString() 直接返回字符串字面量

(2)对象转数字:Number(obj) || Object.prototype.valueOf.(obj)

ToPrimitive(obj,Number)

    - 如果obj是原始类型,则直接返回

    - 否则,调用obj.valueOf(),如果得到原始类型,则返回      

        - 否则,调用obj.toString(),如果得到原始类型,则返回

            - 否则,报错

此时得到的原始类型返回之后再进行原始类型转字符串。

(3)对象转布尔:Boolean(obj)

image.png

所以对象转布尔值都是true。

二、隐式类型转换

前面讲的都是隐式类型转换,接下来我们讲隐式类型转换发生的场景。

1.四则运算

包括 % ,/, * ,+ ,—

2.判断语句

if ,while ,== ,> ,< ,>= , <= , !=

3.一元运算符

加号+,转为数字

+‘123//123

4.二元运算符

val1 + val2

lprim = ToPrimitive(val1)

rprim = ToPrimitive(val2)

只要两边有字符串,那么两边统一转字符串,并拼接。

如果两边都是数字,则相加

两边转换会进行ToPrimitive()转化

5. ==

返回布尔类型

如果两边类型不一样,转number

null == undefined   //true

具体原因我们参照官方文档

image.png

例题

学完之后我们来看一道题

[] == ![]

这个返回什么呢?我们来分析一下

左边:ToPrimitive([],Number) => [].toString() => ' '   =>  ' '.toNumber() => 0
右边:!优先级更高,所以先转布尔,Boolean([])为true。!true => false。Number(false) => 0

所以0 == 0 ,为真。

汇总

image.png

官方文档地址

(es5.github.io/#x11.9.1)