引子: 类型转换涉及到了拆箱装箱,那什么是拆箱装箱?如何进行拆箱装箱?
1.什么是装箱拆箱?
1-1.装箱转换
定义:基本类型 转化为对应的 对象
1-2.拆箱转换
定义:对象 转化为对应的 基本类型。JS 标准规定了ToPrimitive用于拆箱转换。
2. 如何装箱?
2-1.前言
Number、String、Boolean、Symbol、BigInt 都在对象中有对应的类。
联想: 隐藏类 map 仅在 V8 对象中存在,V8 为每一个对象创建一个隐藏类,对象的 map 属性指向隐藏类。在 V8 内存空间中,Map 区存放着隐藏类。(Map 其实也可当作属于老生代) (1)map 定义:类似于静态语言的结构体,假设属性相对于对象的偏移量不会改变(无增删属性) (2)常识:静态语言直接通过偏移量查询对象的属性值,而 JS 是动态语言,偏移量可能会发生变化,需查找。而隐藏类刚好解决了这个问题。 (3)map 作用:提升对象的属性访问速度 (4)map 内容:1.所有属性 2.每个属性相对于对象的偏移量 (5)重构 map: 1.增加属性 2.删除属性 3.改变属性类型 (6)重构 map 会影响程序执行的性能。 (7)代码层面优化:1.避免增删属性 2.字面量初始化对象,属性顺序一致 3.避免改变属性类型。 (8)回收 map: 当不再被任何对象引用时(即无相应结构的对象存在),会被回收。
2-2.Number、String、Boolean
Number、String、Boolean 构造函数 可与new操作符搭配,进行显式装箱,产生对象。也可与.运算符 搭配,进行隐式装箱,产生对象。若可直接调用,则用于强制类型转换。
// 显式装箱
let a = new Number(1)
let b = new String('b')
let c = new Boolean(true)
// 隐式装箱
'lxh'.charAt(0)
2-3.Symbol、BigInt
Symbol、BigInt 构造函数 不可以与 new 搭配,可调用call进行隐式装箱(强制装箱),产生对象。
. 运算符提供装箱操作,根据基础类型构造一个[临时对象],能在基础类型上调用对应对象的原型上的方法。 注意:Object(Symbol())无法满足 instaceof、construtor 指向。
function createSymbolObject(description) {
return function () {
return this
}.call(Symbol(description))
function createBigIntObject(description) {
return function () {
return this
}.call(BigInt(description))
3. 装箱的原理
根据基础类型构造一个临时对象,能在基础类型上调用对应对象的原型上的方法。 该临时对象只存在于方法调用那一行代码执行的瞬间,执行方法后立刻被销毁。
缺点:装箱机制会频繁产生临时对象,尽量避免。
4. 如何拆箱?
4-1.规范
JS 标准规定了ToPrimitive函数用于拆箱转换。ToPrimitive会首先调用valueOf 和toString来获取基本数据类型。
ToPrimitive(input,preferedType?)是 JS 内部算法,input 要转换的值,preferedType 期待转换的类型。 input 为基本数据类型,则直接返回。数据类型为Number时 先调用 valueOf(),再调用 toString() ;数据类型为Stri