Tony Dinh
Tony Dinh

Reputation: 6726

Will the object change its hidden class if we create new prototype properties?

In V8, an object changes its hidden class when a new property is added.

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

My question is simple, will this create a new hidden class?

Point.prototype.z = null;

I ask this question because in a coding style guideline I have read, they said we should declare class properties by creating a prototype instead of assigning them in the constructor. This will also help us to easily document them with JSDoc.

Thanks a lot.

Upvotes: 11

Views: 866

Answers (1)

Vyacheslav Egorov
Vyacheslav Egorov

Reputation: 10492

The answer is yes: a new hidden class will be created. However it's important to understand that it will be the prototype object itself that will change its hidden class, not an object created by the Point constructor.

Any object has a hidden class attached to it. Lets look at the code

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

At any given moment any object has a hidden class, that means o, o.__proto__, o.__proto__.__proto__ have a distinctive hidden class associated with them.

When you add a new property to the object, it's only hidden class of that object that changes. If you change hidden class of the prototype, the hidden classes of objects that share that prototype do not change. There is no need for such a change because we don't expect hidden class of an object X to fully describe the layout of any object in its whole prototype chain, its hidden class describes layout of X and X alone. Furthermore it's simply infeasible to implement such downwards propagation: that would require VM to maintain backward links between prototypes and all associated objects: to be able at any moment for an object X to enumerate all objects Y that have Y.__proto__ === X.

For the code above that means that statement (1) changes only the hidden class of o and statement (2) changes only the hidden class of Point.prototype (which is the same object as o.__proto__) but not of o itself.

Furthermore if you consider the code like this:

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

which is sometimes recommended then this is a performance antipattern precisely because hidden classes of o1 / o2 and Point.prototype are disconnected. Assignment at (3) would change the hidden class of o1 even though o1.__proto__ already has property z. Objects o1 and o2 will end up having different hidden classes which will cause all the code that uses both of them to go polymorphic and penalize the performance. Furthermore o1 will end up using more space than in case if z was added right in the constructor because z would be stored in the out-of-object property storage.

Upvotes: 5

Related Questions