JavaScript 类型转换全面总结

Js中的类型转换一般分为 显示类型转换 和 隐式类型转换 

显式类型转换: 使用包装函数如 Number String Boolean 等对类型进行转换 如Number('3') = 3

隐式类型转换:  不实用包装函数,动态转换。在运算符两侧类型不同的时候,会先进行隐式转换,再进行运算。 如 '1'+0 = '10' [0 转换成字符串'0' 再做运算]     false+10=10  [false转换成数字0 再做运算]

下面具体来看类型之间的相互转换规则!

任意类型转number

  1.  boolean转number类型遵循 false -> 0 true ->1 
  2.  string转number类型遵循 
    1. 如果字符串包含的字符都是数字,会转换成对应的number。如果开头都是0 则忽略,如Number("00100") = 100 。如果开头是"." 会补0 如Number(".0012131") = 0.0012131
    2. 如果包含其他的字符,转换成NaN
    3. 如果是空字符串"",或者仅有空格的字符串. " "  , "   " , "       "  ... ,转换成0

总结一下: 能转成数字的转数字,不能转的一律转成NaN

      3. Symbol类型无法转换成number类型,会直接报错

      4. 特殊的空值转number: undefined -> NaN.    null -> 0 (null转为0也是C语言的传统)

      5. 复杂类型转number类型,会先进行[[Primitive]]操作,求其原始值,再将其原始值按照上述规         则转换成简单类型。

[[Primitive]]操作

[[Primitive]]操作是javascript引擎的内置方法,其作用是将复杂类型转换成简单类型的原始值.

具体流程如下:

        1. 调用复杂类型的valueOf方法,如果返回的是一个简单类型,则返回该值。结束

        2. 如果不是简单类型,则调用复杂类型的toString方法,如果返回简单类型,则返回该值,结束。

        3. 如果还不是简单类型,返回undefined 结束       

我们举一些例子:

DEMO1
const obj = {} 
Number(obj) = NaN

obj 为复杂类型,所以在转换之前,js引擎会先调用[[Primitive]]操作,将其转换为基本类型,具体流程为:
1. 调用{}的valueOf方法,其返回值为{}本身,不是一个简单类型
2. 调用{}的toString方法,返回值为 "[object Object]" 是一个简单类型
此时就转换成了 Number("[object Object]") 而  "[object Object]" 无法转换成数字,所以返回NaN

这里你或许会疑问,为什么obj.toString() 为 “[object Object]” ?

这是因为,obj对象本身不存在toString函数,所以会顺着其原型链查找,找到Object.prototype对象。

Object.prototype对象中的toString默认会返回obj对象中的[[Class]]内置属性,在普通对象中,该属性默认值为"[object Object]"

我们可以通过 Object.prototype.toString.call() 插件这个值以及其子类型,这里要用call改变Object.prototype.toString函数的this指向,否则其会一直指向 Object.prototype

 

DEMO 2
const arr = [] 
Number(arr) = 0
这里由于数组arr是个复杂类型,要先调用[[Primitive]]操作将其转换为普通类型
1. arr.valueOf 返回的也是其本身
2. 由于数组是Array构造函数的实例,Array.prototype上实现了专用于数组的toString方法,所以arr.toString()会调用这个方法,将数组元素用","拼接,并且返回一个数组,由于arr为空,返回空字符串“”
3. 由于空字符串是普通类型,所以就变成了 Number("") = 0 
DEMO 3
const arr = [11]
Number(arr) = 11
和上面的例子类似,[11]转换为普通类型,调用其toString函数,返回"11" 转换成Number(11) = 11

DEMO 4
const arr = [‘abc’] 
Number(arr) = NaN
同理,['abc'] 转换为简单类型为 'abc' Number('abc') = NaN

DEMO 5 
const arr = [1,2]
Number(arr) = NaN
arr转换成简单类型为 "1,2" Number("1,2") = NaN
DEMO 6
const arr = [null]

DEMO 7
const arr = [undefined]

DEMO 8
const arr = [null,undefined]

这三个一起看 按照上面的例子,你也许会觉得 这三个答案都是NaN
[null] -> 'null' Number('null') = NaN
[undefined] -> 'undefined' Number('undefined') = NaN
[null,undefined] -> 'null,undefined' Number('null,undefined') =NaN

但是其实并不是这样
Array中的toString函数 在遇到null或者undefined时,会跳过,不会加入到最终的字符串中,所以DEMo6 7 的原始值都是 '' 最终结果为 0 而最后一个虽然undefined和null都会跳过,但是两个空字符串会被","链接,所以其原始值为 "," Number(",") = NaN
DEMO 9 
Number(new Date())  = 1706000941594 (当前时间的时间戳)
很好理解了 (new Date()).valoeOf() 为当前时间戳,正好也是该Date对象的原始值

所以又获得了一个新的获取时间戳的办法 +(new Date())

任意类型转boolean

这个只需要记住转换为false的情况,剩下的都为false

1. 字符串中,只有空字符串为false,包含空格的字符串都是true 如'  '

2. 数字中 NaN +0 -0 为false 其他都是true

3.复杂类型都是true

4.Symbol类型都是true

5. undefined 和 null 都是false

需要注意,new Boolean(false) 是个复杂对象,即便传入的是false,其构造的对象也是true

请不要写 if(new Boolean(false)){} 这样的代码!

任意类型转String 

1. boolean转string false-> "false" true->"true"

2. 数字转string

        1. 正常数字直接包裹成字符串

        2. NaN -> "NaN"

        3. Infinity -> "Infinity" -Infinity -> "-Infinity"

        4. 0 +0 -0 -> "0"

3. 复杂类型转字符串,会直接调用其内部的toString方法

4. Symbol转字符串,如果是显式转换,即String(Symbol(111)) 则相当于调用Symbol().toString()函数 转换成Symbol(111) 如果是隐式转换 如 Symbol(111)+'111' 会报错 这个记一下

Symbol转换

Symbol转string number boolean上面总结过了,即:

1. Symbol转string 显式转换可以成功 隐公转换报错

2. Symbol转number 会报错

3. Symbol转boolean 一律都是true

任意类型转Symbol 会先转成字符串,然后作为Symbol的描述,如

function foo(){}
console.log(Symbol(foo)) //Symbol(function foo(){})

任意类型转JSON字符串

使用JSON.stringify可以将任意类型转成JSON字符串,使用JSON.parse() 可以解析还原JSON字符串。

但是有些类型转成JSON是不安全的,在parse时,无法还原,包含以下几种情况:

1. undefined 函数 Symbol等 直接stringify会返回undefined,在对象中会直接忽略,在数组中会直接转成 null 如:

2. null NaN +Infinity -Infinity 都会转换成 "null"

3. 对于一些重写了toJSON的函数,会先调用toJSON方法,将其返回值按照规则转换 如moment

4. RegExp Error 这些方法也包含toJSON,其创建的实例对象的JSON转换后为 “{}”

5. 对象的原型链在stringify后会丢失

6. 循环引用转JSON时会报错

面试中,我经常被问过一个问题

有什么办法能拷贝对象?

Object.assign / {...obj}

还有没有别的办法能深拷贝对象?

JSON.parse(JSON.stringify(obj)) 

那这种办法有什么问题? 这时候你就知道怎么回答了!

ps: 一般这种需要递归写一个拷贝函数 你如果懒得写 还有loash给你用!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值