持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
什么是装箱和拆箱?
总体来说,只要是有“对象”这一个概念的语言,都有相应的装箱和拆箱转换。
JavaScript的装箱和拆箱
装箱转换
(1)基本类型转换为对应对象类型的转换。
(2)每一种基本类型在对象中都有对应的类。
//举个栗子
Number 和 new Number()
String 和 new String()
Boolean 和 new Boolean()
Symbol 和 new Symbol()
每一类装箱对象都有私有的[[class]]属性,可以通过Object.prototype.toString得到。JavaScript中没有方法可以更改私有的[[class]]属性,因此用call函数强制执行Objec。prototype.toString到新生成的对象上,就可以准确识别对象对应的基本类型的方法。比instanceof更准确。但是,因为call本身会产生装箱操作,所以需要配合typeof来区分基本类型还是对象类型。
此处呼应文章juejin.cn/post/708375… 中评论里回复中我举的例子。
(3)装箱转换时会产生临时对象,在性能要求较高的情况下,应尽量避免对基本类型做装箱转换。
拆箱转换
(1)对象类型到基本类型的转换。
(2)拆箱转换会尝试调用对象的valueOf和toString来得到拆箱后的基本类型。如果valueOf和toString都不存在,或者没有返回基本类型,会抛出类型错误(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。
总结
请问,文中一共举了几个栗子?