Mostly this property is used for defining a function as a function-constructor with further calling it with new and prototype-inherits chain.
function Parent() { }
Parent.prototype.parentMethod = function parentMethod() {}
function Child() {
Parent.call(this)
}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
But when do we need to perform the last line here? Unfortunately, the answer is: it depends.
Let's try to define the cases in which re-assignment of the original constructor will play a major role, and when it will be one superfluous line of code.
Take the following case: the object has the create()
method to create itself.
function Parent() { }
function CreatedConstructor() {
Parent.call(this)
}
CreatedConstructor.prototype = Object.create(Parent.prototype)
CreatedConstructor.prototype.create = function create() {
return new this.constructor()
}
new CreatedConstructor().create().create()
In the example above the exception will be shown since the constructor links to Parent.
To avoid this, just assign the necessary constructor you are going to use.
function Parent() { }
function CreatedConstructor() { }
CreatedConstructor.prototype = Object.create(Parent.prototype)
CreatedConstructor.prototype.constructor = CreatedConstructor
CreatedConstructor.prototype.create = function create() {
return new this.constructor()
}
new CreatedConstructor().create().create()
Ok, now it's pretty clear why changing the constructor can be useful.
Let's consider one more case.
function ParentWithStatic() {}
ParentWithStatic.startPosition = { x: 0, y:0 }
ParentWithStatic.getStartPosition = function getStartPosition() {
return this.startPosition
}
function Child(x, y) {
this.position = {
x: x,
y: y
}
}
Child.prototype = Object.create(ParentWithStatic.prototype)
Child.prototype.constructor = Child
Child.prototype.getOffsetByInitialPosition = function getOffsetByInitialPosition() {
let position = this.position
let startPosition = this.constructor.getStartPosition()
return {
offsetX: startPosition.x - position.x,
offsetY: startPosition.y - position.y
}
};
For this example to work properly we need either to keep Parent
as the constructor or reassign static properties to Child
's constructor:
...
Child = Object.assign(Child, ParentWithStatic);
Child.prototype = Object.create(ParentWithStatic.prototype);
...
or assign Parent
's constructor identifier to a separate property on the Child
constructor function and access it via that property:
...
Child.parentConstructor = ParentWithStatic
Child.prototype = Object.create(ParentWithStatic.prototype)
...
let startPosition = this.constructor.parentConstructor.getStartPosition()
...
Note: Manually updating or setting the constructor can lead to different and sometimes confusing consequences. To prevent this, just define the role of constructor
in each specific case. In most cases, constructor
is not used and reassignment of it is not necessary.