Reputation: 39457
Object.getPrototypeOf(z).constructor === z.constructor
Is this true for every object z
in JavaScript?
I mean is z.constructor
just a shortcut allowing us to retrieve more easily
the constructor property of the object's internal [[Prototype]]
property.
Or... are there cases in which the two differ and the z.constructor
value
is different from the Object.getPrototypeOf(z).constructor
value?
I think it is just shortcut but I am not sure as I don't find
this stated explicitly in any authoritative source of doc.
EDIT:
This code below shows that setting Object.getPrototypeOf(z).constructor
implicitly sets the other value too. But setting z.constructor
does not set the other value.
So now I am puzzled... how is this implemented? Seems z.constructor
is not just a shortcut but some sort of copy. But if it's a copy why is it affected when we change/set the Object.getPrototypeOf(z).constructor
to a new value?
function Animal() {
this.ttype = "Animal"
}
function Plant(){
this.ttype = "Plant"
}
var p1 = new Plant();
console.log(p1.constructor);
console.log(p1.constructor === Object.getPrototypeOf(p1).constructor);
p1.constructor = Animal;
console.log(p1.constructor === Object.getPrototypeOf(p1).constructor);
var p2 = new Plant();
console.log(p2.constructor);
console.log(p2.constructor === Object.getPrototypeOf(p2).constructor);
Object.getPrototypeOf(p2).constructor = Animal;
console.log(p2.constructor === Object.getPrototypeOf(p2).constructor);
console.log(p2.constructor);
Upvotes: 0
Views: 57
Reputation: 19301
The constructor
property of an object is normally inherited from it's prototype chain. There are two exceptions:
Objects whose prototype chain doesn't contain any objects. These be created using Object.create(null)
and are useful for setting up look up tables that aren't affected by properties inherited from somewhere else.
Objects that have been assigned a local "own" property called constructor
, as in
myObject.constructor = 42;
However, this is a technicality and not something you would expect to see in real code.
So leaving these aside, where is constructor
inherited from?
By language design, constructor
is inherited from the constructor function's prototype
property. Every plain vanilla function in JavaScript is set up with a prototype
property with a non enumerable property called constructor
set to the function object itself. By this means any standard function can be called as a constructor without modification. However the overhead is that standard functions never intended to be used as constructors have a prototype
property anyway.
Now more complications:
The prototype
property of a standard function object is writable. If it is updated to a new object value, objects constructed by the function will inherit constructor
from the ammended prototype
object - which would generally be different to the constructor
value of the overwritten prototype
value.
The constructor
property of the prototype
property of a function is not write protected.
In combination, these two factors allow setting up prototype chains of arbitrary length, simulating in part the extension of classes in a class based language. E.G. If C
objects inherit from B
which inherit from A
you could write
B.prototype = new A() // B objects inherit from an instance of A,
// which inherits from A.prototype
C.prototype = new B() // C objects inherit from an instance of B,
// which inherits from B.prototype and A.prototype
C.prototype.constructor = C; // C objects inherit C as their constructor.
These classic rules for chaining prototypes are quite lax: you can change the prototype
property multiple times without affecting the inheritance chain of previously created objects. However changing the prototype
property of a constructor function multiple times has limited use (creating a polyfill for Object.create
perhaps) and most unusual.
Note the class
keyword syntax to create constructor functions renders this kind of manipulation obsolete - you can't change a class constructor functions prototype
property, and if you extend a "class" the prototype
property of the extended class inherits from the base class's prototype
property while having its constructor
property set to the extended constructor, both automatically.
Also note that arrow functions don't have a prototype
property and cannot be used as constructors.
q1
Object.getPrototypeOf(z).constructor === z.constructor
Is this true for every object z in JavaScript?
Yes, except for the exceptions listed under 1) and 2).
q2
p1.constructor = Animal;
This creates an own property of p1
that shadows the inherited constructor
property which can no longer be accessed (exception 2)
q3
Object.getPrototypeOf(p2).constructor = Animal;
This line of code updates the constructor
property of the object from where p2
inherits its constructor
value from, so p2
's inherited constructor property is now Animal
. Other plant objects which similarly inherit from Plant.prototype
would also see Animal
as their constructor.
Upvotes: 1