好玩的隐藏属性
隐藏类
- 对象中所包含所有属性
- 每个属性相对于对象的偏移量
let point = {x:100,y:200}
-
在v8中隐藏类又称为map,每个对象都有一个map属性,其值指向存储中的隐藏类
-
有了map之后,point.x访问x属性时,v8会先查询point的map中x属性相对point对象的偏移量,然后将point对象的起始值加上偏移量,就得到x属性的值在内存的位置,有了这个位置也就拿到了x的值
-
使用d8看看隐藏类
let point = {x:100,y:200};
%DebugPrint(point);
d8 --allow-natives-syntax test.js
DebugPrint: 0x4eb080c6019: [JS_OBJECT_TYPE]
- map: 0x04eb08284ce9 <Map(HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x04eb08241395 <Object map = 0x4eb082801c1>
- elements: 0x04eb080406e9 <FixedArray[0]> [HOLEY_ELEMENTS]
- properties: 0x04eb080406e9 <FixedArray[0]> {
#x: 100 (const data field 0)
#y: 200 (const data field 1)
}
0x4eb08284ce9: [Map]
- type: JS_OBJECT_TYPE
- instance size: 20
- inobject properties: 2
- elements kind: HOLEY_ELEMENTS
- unused property fields: 0
- enum length: invalid
- stable_map
- back pointer: 0x04eb08284cc1 <Map(HOLEY_ELEMENTS)>
- prototype_validity cell: 0x04eb081c0451 <Cell value= 1>
- instance descriptors (own) #2: 0x04eb080c6049 <DescriptorArray[2]>
- prototype: 0x04eb08241395 <Object map = 0x4eb082801c1>
- constructor: 0x04eb082413b1 <JSFunction Object (sfi = 0x4eb081c557d)>
- dependent code: 0x04eb080401ed <Other heap object (WEAK_FIXED_ARRAY_TYPE)>
- construction counter: 0
多个对象共用一个隐藏类
- 相同的属性名称
- 相同的属性个数
let point = {x:100,y:200};
let point2 = {x:3,y:4};
%DebugPrint(point);
%DebugPrint(point2);
d8 --allow-natives-syntax test.js
DebugPrint: 0x3e0a080c6075: [JS_OBJECT_TYPE]
- map: 0x3e0a08284ce9 <Map(HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x3e0a08241395 <Object map = 0x3e0a082801c1>
- elements: 0x3e0a080406e9 <FixedArray[0]> [HOLEY_ELEMENTS]
- properties: 0x3e0a080406e9 <FixedArray[0]> {
#x: 100 (const data field 0)
#y: 200 (const data field 1)
}
DebugPrint: 0x3e0a080c60cd: [JS_OBJECT_TYPE]
- map: 0x3e0a08284ce9 <Map(HOLEY_ELEMENTS)> [FastProperties]
- prototype: 0x3e0a08241395 <Object map = 0x3e0a082801c1>
- elements: 0x3e0a080406e9 <FixedArray[0]> [HOLEY_ELEMENTS]
- properties: 0x3e0a080406e9 <FixedArray[0]> {
#x: 3 (const data field 0)
#y: 4 (const data field 1)
}
重新构建隐藏类
- 对象创建好后添加新的属性
- 对象创建好后删除属性
let point = {};
%DebugPrint(point);
point.x = 100;
%DebugPrint(point);
point.y = 200;
%DebugPrint(point);
d8 --allow-natives-syntax test.js
DebugPrint: 0x986080c5b35: [JS_OBJECT_TYPE]
- map: 0x0986082802d9 <Map(HOLEY_ELEMENTS)> [FastProperties]
- ...
DebugPrint: 0x986080c5b35: [JS_OBJECT_TYPE]
- map: 0x098608284ce9 <Map(HOLEY_ELEMENTS)> [FastProperties]
- ...
- properties: 0x0986080406e9 <FixedArray[0]> {
#x: 100 (const data field 0)
}
DebugPrint: 0x986080c5b35: [JS_OBJECT_TYPE]
- map: 0x098608284d11 <Map(HOLEY_ELEMENTS)> [FastProperties]
- p
- ...
- properties: 0x0986080406e9 <FixedArray[0]> {
#x: 100 (const data field 0)
#y: 200 (const data field 1)
提升对象属性的查找性能,减少隐藏类的创建次数和存储空间
- 使用字面量初始化对象时,要保证属性的顺序是一致的
- 尽量一次性初始化完整的对象属性
- 尽量避免使用delete方法
// 顺序不一样,导致形状不同,所以会创建不同的隐藏类
let point = {x:100,y:200};
let point2 = {y:100,x:200};
%DebugPrint(point);
%DebugPrint(point2);
- map: 0x31d008284ce9 <Map(HOLEY_ELEMENTS)> [FastProperties]
- map: 0x31d008284d39 <Map(HOLEY_ELEMENTS)> [FastProperties]