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.
[[Prototype]] In JavaScript, objects have a special hidden property [[Prototype]] (as named in the specification), that is either null or references another object. That object is called “a prototype”: When we read a property from object , and it's missing, JavaScript automatically takes it from the prototype.
Conceptually, all objects have a prototype (NOT A PROTOTYPE PROPERTY). Internally, JavaScript names an object's prototype as [[Prototype]]. There are two approaches to get any object (including non-function object)'s [[prototype]]: the Object. getPrototypeOf() method and the __proto__ property.
Every object with its methods and properties contains an internal and hidden property known as [[Prototype]]. The Prototypal Inheritance is a feature in javascript used to add methods and properties in objects. It is a method by which an object can inherit the properties and methods of another object.
prototype is a property of a Function object. It is the prototype of objects constructed by that function. __proto__ is an internal property of an object, pointing to its prototype.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With