JS中的内存占用
JS中的内存占用 前言 思考下面的 r1 和 r2 谁占用的内存更多?
tsconst o = {id: 1}
const r1 = [o]
const r2 = [o.id]1234JS不同类型的内存占用 在 V8 引擎(Chrome / Node.js)中:
基本类型 Number:在数组中作为元素存储时,Smi(小整数)模式下占用 4 字节(存储在栈/数组内部),HeapNumber 模式下占用对象头 + 8 字节数据。String:可变,取决于长度和编码(UTF-8 1~4字节/字符,UTF-16 2字节/字符,且 JS 内部是 UTF-16)。Boolean、Undefined、Null:在数组中同样以标记指针形式存在,占用 4 字节(指针压缩模式下)。引用类型 Object:至少占用对象头(Map 指针 + 属性存储指针),在指针压缩模式下为 8 字节头,加上内联属性空间。Array:本质是特殊 Object,额外有 length 等内部字段。元素存储方式取决于元素类型(Smi 数组、Double 数组、对象指针数组)。引用本身:在 64 位指针压缩模式下为 4 字节,非压缩模式下 8 字节。分析 tsconst o = {id: 1}
const r1 = [o] // 数组中存的是 o 的引用(4 字节)
const r2 = [o.id] // 数组中存的是 Smi 值 1(4 字节)1234如果只看数组内元素,r1 存的是引用(指针压缩下 4 字节),r2 存的也是 Smi(4 字节),单从"数组元素"角度来看占用相同。
但 r1 引用了对象 o,只要 r1 存在,o 就无法被 GC 回收。o 本身还占据内存(16+ 字节)。因此:
r1 方案总体内存占用更高,因为还额外持有一个对象 o 的引用 → o 必须存活。如果 o 已经被其他地方引用而始终在内存中,那 r1 和 r2 的元素占用差别不大,但 r1 多了一层引用追踪。更关键的区别 r1 存对象引用r2 存原始值修改 o.id 后能通过 r1[0] 看到变化✅❌o 可以被 GC(无其他引用时)❌(r1 持有引用)✅序列化(JSON)能还原完整结构只能还原值结论 这道题粗看会去比"指针 vs Number 几字节",但实际更有意义的是所有权和 GC 语义——存对象引用会延长对象生命周期,存原始值则完全解耦。选择哪种写法取决于你是需要与源对象保持实时关联,还是只需要那一刻的快照值。