前端问题清单——JavaScript的装箱转换和拆箱转换

142 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

什么是装箱和拆箱?

总体来说,只要是有“对象”这一个概念的语言,都有相应的装箱和拆箱转换。

JavaScript的装箱和拆箱

装箱转换

(1)基本类型转换为对应对象类型的转换。

(2)每一种基本类型在对象中都有对应的类。

//举个栗子
Numbernew Number()
Stringnew String()
Booleannew Boolean()
Symbolnew Symbol()

每一类装箱对象都有私有的[[class]]属性,可以通过Object.prototype.toString得到。JavaScript中没有方法可以更改私有的[[class]]属性,因此用call函数强制执行Objec。prototype.toString到新生成的对象上,就可以准确识别对象对应的基本类型的方法。比instanceof更准确。但是,因为call本身会产生装箱操作,所以需要配合typeof来区分基本类型还是对象类型。

此处呼应文章juejin.cn/post/708375… 中评论里回复中我举的例子。

(3)装箱转换时会产生临时对象,在性能要求较高的情况下,应尽量避免对基本类型做装箱转换。

拆箱转换

(1)对象类型到基本类型的转换。

(2)拆箱转换会尝试调用对象的valueOftoString来得到拆箱后的基本类型。如果valueOftoString都不存在,或者没有返回基本类型,会抛出类型错误(TypeError)。

//再举个栗子
1、对象对应的基本类型是数值时
let obj = {
valueOf: ()=>{return {}}
toStirng: ()=>{return {}}
}
obj*2
此时会抛出异常。转换顺序如下:先查看valueOf是否存在,存在,调用valueOf,发现没有返回基本类型,再查看toString是否存在,存在,调用toString,也没有返回基本类型,就会抛出类型错误
2、对象对应的基本类型是字符串时
let obj = {
valueOf: ()=>{return {}},
toString: ()=>{return'aaa'}
}
String(obj)
此时会显示'aaa'。转换顺序如下:先查看toString是否存在,存在,调用toString,返回基本类型和内容,就会展示为'aaa'

(3)JavaScript标准规定了toPrimitive函数来做拆箱转换。在ES6加入了Symbol之后,允许对象显式指定Symbol.toPrimitive覆盖原有行为。

//复举上一个栗子,对象对应的基本类型是字符串
let obj = {
valueOf: ()=>{return {}},
toString: ()=>{return'aaa'}
}
obj[Symbol.toPrimitive] = ()=>{return 'string'}
String(obj)
此时会显示'string'

一些常见的转换

(1)==运算:一种可以跨类型的比较。

//我觉得可能是最后一个举栗子
true=='aa'
不要运行,脑中第一反应:true or false?
结论是false
因为==有一边是字符串,另一边也要转为字符串,true=》'true',那必然是false
为了转换更加的可控或者避免产生一些可能会出现的问题,建议还是使用===,两边在经过显式的转换后再比较。
比如栗子中的两个数据,就是想使用布尔值来比较,可以写成true === Boolean('aa'),这个表达式就是true了。

(2)字符串转数字

当你在对一个字符串转数字的时,字符串不小心掉入河里,河神说:亲爱的少年哟,你是用什么方法把字符串转成数字的呢?

a.神奇的parseInt函数,重点关注第二个参数

b.parseFloat,直接解析为十进制

c.Number

两长一短选最短,真的,信我,选c。

总结

请问,文中一共举了几个栗子?