【问题标题】:Will the object change its hidden class if we create new prototype properties?如果我们创建新的原型属性,对象会改变它的隐藏类吗?
【发布时间】:2014-08-04 02:40:16
【问题描述】:

在 V8 中,当添加新属性时,对象会更改其 hidden class

function Point(x, y) {
  this.x = x; // This will create new hidden class
  this.y = y; // This too
}

我的问题很简单,这会创建一个新的隐藏类吗?

Point.prototype.z = null;

我问这个问题是因为在我读过的编码风格指南中,他们说我们应该通过创建原型来声明类属性,而不是在构造函数中分配它们。这也将有助于我们使用 JSDoc 轻松记录它们。

非常感谢。

【问题讨论】:

  • 我不知道 V8 的细节,但是在原型上声明属性会占用更少的内存,以防万一这是相关的考虑因素。但要小心避免无意共享对象属性(请参阅bennadel.com/blog/…)。
  • 接受的答案不正确。应该不会运行的代码在 jsBin (jsbin.com/hawuhoga/1/edit?js,console) 中执行得很好。它断言原型在对象构造时被复制是完全错误的。

标签: javascript prototype v8 internals


【解决方案1】:

答案是:将创建一个新的隐藏类。然而,重要的是要了解,将改变其隐藏类的是 prototype 对象本身,而不是由 Point 构造函数创建的对象。

任何对象都有一个附加的隐藏类。看代码

var o = new Point();
o.z = 0;  // (1)
Point.prototype.zz = 0;  // (2)

在任何给定时刻,任何对象都有一个隐藏类,这意味着oo.__proto__o.__proto__.__proto__ 具有与之关联的独特隐藏类。

当您向对象添加新属性时,只会更改该对象的隐藏类。如果您更改原型的隐藏类,则共享该原型的对象的隐藏类不会改变。没有必要进行这样的更改,因为我们不期望对象X 的隐藏类完全描述其整个原型链中任何对象的布局,它的隐藏类仅描述XX 的布局.此外,实现这种向下传播是不可行的:这将需要 VM 维护原型和所有关联对象之间的反向链接:能够在任何时候让对象X 枚举具有Y.__proto__ === X 的所有对象Y

对于上面的代码,这意味着语句(1) 更改 o 的隐藏类和语句(2) 更改 @987654334 的隐藏类@(与 o.__proto__ 相同的对象)但 不是 o 本身。

此外,如果您考虑这样的代码:

Point.prototype.z = 0;  // Initial value
var o1 = new Point();
o1.z = 11;  // (3)
var o2 = new Point();

有时会推荐这是一种性能反模式,因为 o1 / o2Point.prototype 的隐藏类是断开连接的。 (3) 的赋值将改变 o1 的隐藏类,即使 o1.__proto__ 已经具有属性 z。对象o1o2 最终将具有不同的隐藏类,这将导致使用它们的所有代码变为多态并降低性能。此外,o1 最终将使用比在构造函数中直接添加 z 的情况更多的空间,因为 z 将存储在对象外属性存储中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-17
    • 2013-12-09
    • 2016-03-26
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 2014-08-03
    • 1970-01-01
    相关资源
    最近更新 更多