0003装箱拆箱

347 阅读3分钟

引子: 类型转换涉及到了拆箱装箱,那什么是拆箱装箱?如何进行拆箱装箱?


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会首先调用valueOftoString来获取基本数据类型

ToPrimitive(input,preferedType?)是JS内部算法,input要转换的值,preferedType期待转换的类型。

input为基本数据类型,则直接返回;Number先调用valueOf(),String先调用toString()。

若两属性均无,或没有返回基本类型,则会产生类型错误 TypeError: Cannot convert object to primitive value

4-2.操作

定义valueOf和toString

复杂数据类型在隐式转换时,先调用 valueOf,再调用 toString。

空数组的toString()方法会得到空字符串,而空对象的toString()方法会得到字符串[object Object]

let success_unpack = {
    valueOf: () => 7,
    toString: () => 8,
}
console.log(Number(success_unpack)); // 7 Number拆箱: valueOf, toString, TypeError
console.log(String(success_unpack)); // 8 String拆箱: toString, valueOf, TypeError