The question is published on by Tutorial Guruji team.
I know that in order to bind a property to a function you need to add that to its prototype. For example:
function Animal(name) { this.name = name; }; Animal.prototype.number = 20; Animal.prototype.bark = function() {console.log('Woof')}; let mike = new Animal('Mike'); console.log(mike.number) mike.bark();
Perhaps this is a very naive question, but why are you not allowed to bind a property to the function itself? For example, doing the following:
function Animal(name) { this.name = name; }; Animal.bark = function() {console.log('Woof')}; Animal.number = 20; let mike = new Animal('Mike'); console.log(mike.number) mike.bark();
Answer
Objects in JavaScript use prototypal inheritance. Every object inherits from some other object, or from null
. This chain continues – all objects eventually inherit from null
.
If an object inherits from another, all of the properties available on the parent object will be available on the child object (unless the child object defines a property with the same name, effectively shadowing and hiding the name on the parent).
If instances of Animal inherited from Animal itself, like with
function Animal(name) { this.name = name; }; Animal.bark = function() {console.log('Woof')}; Animal.number = 20;
Then instances of Animal would be inheriting from function Animal
, which is a function – and would be functions and would also inherit .call
, .apply
, and so on. This is almost never what a developer would want.
Having a separate controllable object that instances inherit from makes more sense, and it was decided to make that object referenceable through <functionName>.prototype
.
The prototype chain is:
instance <- Animal.prototype <- Object.prototype
and
Animal <- Function.prototype <- Object.prototype
Having instances also inherit from Function.prototype
and be functions just wouldn’t make sense. One almost always wants ordinary objects as instances, not callable functions.
Another benefit of having Animal.prototype
being separate from Animal
is that you can have both properties on the prototype and properties on the function or class itself, which is a nice way to separate instance values and methods from utility values and functions – which are associated with the class, but don’t have to do with any instance in particular.
function Animal(name) { this.name = name; }; Animal.prototype.bark = function() {console.log(this.name + ' says Woof')}; Animal.checkIsAnimal = function(possibleAnimal) { console.log('Is this an animal? ' + (possibleAnimal instanceof Animal)); }; const mike = new Animal('Mike'); Animal.checkIsAnimal({}); Animal.checkIsAnimal(mike);