因为应用字典查找内存中对象属性的地位效力异常低,是以 V8 应用了不合的办法:隐蔽类。隐蔽类与 Java 等说话中应用的固定对象(类)的工作方法类似,除了隐蔽类是在运行时创建的┞封点差别。如今,让我们看看他们实际的例子:
- function Point(x, y) {
- this.x = x;
- this.y = y;
- }
- var p1 = new Point(1, 2);
一旦 “new Point(1,2)” 调用产生,V8 将创建一个名为 “C0” 的隐蔽类。

为什么创建 V8 引擎?
一旦第一个语句 “this.x = x” 被履行(在 “Point” 函数内部),V8 将创建第二个隐蔽的类,名为“C1”,它基于“C0”。 “C1”描述了可以找到属性x的在内存中的地位(相对于对象指针)。在这种情况下,“x”被存储在0处,这意味着当在内存中将点对象看作一段持续存储空间时,第一个地址将对应于属性“x”。 V8 也会用“class transition”来更新“C0”,如不雅一个属性“x”被添加到一个点对象时,隐蔽类应当大年夜“C0”切换到“C1”。下面的点对象的隐蔽类如今是“C1”。

每当一个新的属性被添加到一个对象时,旧的隐蔽类将被更新为到新的隐蔽类的转换路径。隐蔽的类转换异常重要,因为它们许可隐蔽的类在以雷同方法创建的对象之间共享。如不雅两个对象共享一个隐蔽类,并将雷同的属性添加到这两个对象,则转换精确保两个对象接收雷同的新隐蔽类和所有优化代码。
尚未为 Point 定义属性,是以“C0”为空。
当语句 “this.y = y” 被履行时,会反复同样的过程(在 “Point” 函数内部,“this.x = x”语句之后)。

隐蔽类转换取决于将属性添加到对象的次序。看看下面的代码片段:
- function Point(x, y) {
- this.x = x;
- this.y = y;
- }
- var p1 = new Point(1, 2);
- p1.a = 5;
- p1.b = 6;
- var p2 = new Point(3, 4);
- p2.b = 7;
- p2.a = 8;
如今,假设对于p1和p2,将应用雷同的隐蔽类和转换。那么,对于“p1”,起首添加属性“a”,然后添加属性“b”。然而,“p2”起首分派“b”,然后是“a”。是以,因为不合的转换路径,“p1”和“p2”以不合的隐蔽类别停止。在这种情况下,以雷同的次序初始化动态属性好得多,以便隐蔽的类可以被重用。
内联缓存
它是如何工作的? V8 保护一个在比来的办法调用中作为参数传递的对象类型的缓存,并应用这些信息来猜测将来作为参数传递的对象的类型。如不雅V8可以或许很好地假定传递给办法的对象类型,那么它可以绕过若何拜访对象的属性的过程,而是将之前查找到的信息用于对象的隐蔽类。
那么隐蔽类和内联缓存的概念若何相干呢?无论何时在特定对象上调用办法时,V8 引擎都必须履行对该对象的隐蔽类的查找,以肯定拜访特定属性的偏移量。在同一个隐蔽类的两次成功的调用之后,V8 省略了隐蔽类的查找,并简单地将该属性的偏移量添加到对象指针本身。对于该办法的所有下一次调用,V8 引擎都假定隐蔽的类没有更改,并应用大年夜以前的查找存储的偏移量直接跳转到特定属性的内存地址。这大年夜大年夜进步了履行速度。
内联缓存也是为什么雷同类型的对象可以共享隐蔽类异常重要的原因。如不雅你创建了两个雷同类型的对象和不合的隐蔽类(就像我们之前的例子中那样),V8 将不克不及应用内联缓存,因为即使两个对象是雷同的类型,它们响应的隐蔽类为其属性分派不合的偏移量。
推荐阅读
开辟者大年夜赛路演 | 12月16日,技巧立异,北京不见不散 为什么今天要写出来?为什么是今天要写如许一篇文┞仿?这篇文┞仿是我混迹linux世界这么久一向想说的很多话的集合,大年夜岁首?年>>>详细阅读
本文标题:解读JavaScript之V8引擎及优化代码的5个技巧
地址:http://www.17bianji.com/lsqh/39844.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示