我已经阅读了V8中隐藏的类,并在d8调试器shell中进行了一些测试。
function Vector(a, b) {
this.a = a;
this.b = b;
}
var x = new Vector(1, 2);
var y = new Vector(1, 3);
var z = new Vector(1, 'a');
print( %HaveSameMap( x, y ) ); //true
print( %HaveSameMap( x, z ) ); //false
x.b;
print( %HaveSameMap( x, z ) ); //true
print( %HaveSameMap( y, z ) ); //false
y.b;
print( %HaveSameMap( y, z ) ); //true
因为我们可以看到对象属性类型是否不同,所以在我们尝试访问类型不同的老对象中的属性之前,它们不共享它们的隐藏类。任何人都可以清楚地解释“幕后”发生了什么,也许它与内联缓存有关。
答案 0 :(得分:4)
V8开发者在这里。简而言之,正在发生的事情是“隐藏类”不仅存储属性的存在信息,还存储有关其值的(相对粗粒度)类型信息。为了避免有太多不同的隐藏类,在触摸对象时它们会被合并。
在你的例子中:
var x = new Vector(1, 2);
var y = new Vector(1, 3);
x
和y
现在都有一个隐藏的类HC1
知道“我有一个属性.b
,它的值总是一个小整数(又名Smi)“。但后来发生了这种情况:
var z = new Vector(1, 'a');
因此z
需要该隐藏类的更新版本,因为其.b
的值是一个字符串。 V8目前还没有记住“值可以是整数或字符串”;相反,它只是丢弃类型信息。因此,z
会获得一个新的隐藏类HC2
,它知道“我有一个属性.b
(但我对它的价值一无所知,它可能是任何东西)” 。创建此隐藏课程HC2
后,HC1
会被标记为“过时”;但为了节省时间,我们没有努力使用HC1
查找和更新对象。当你运行
x.b;
然后V8必须查看x
及其隐藏的类HC1
,并注意到HC1
已被标记为“过时”,因此它会找到更新后的版本{{1并更新HC2
以使用它。
优化像JavaScript这样的动态语言非常复杂; - )