The fact that Javascript uses functions to create objects was confusing to me at first. An example like this is often used to highlight how prototypes work in Javascript:
function Car(){
this.setModel=function(model){
this.model=model;
}
this.getModel=function(){
return this.model;
}
}
function Bus(){}
Bus.prototype=new Car();
var obj=new Bus();
obj.setModel('A Bus');
alert(obj.getModel('A Bus');
Is it possible to use prototypes without using new FunctionName()
? I.e. something like this:
var Car={
setModel:function(model){
this.model=model;
},
getModel:function(){
return this.model
}
}
var Bus={
prototype:Car;
};
var obj=Bus;
obj.setModel('A Bus');
alert(obj.getModel());
This does not use functions and new
to create objects. Rather, it creates objects directly.
Is this possible without deprecated features like Object.__proto__
or experimental functions like Object.setPrototypeOf()
?
Prototypes allow you to make new object instances from other object instances. The new instance stands on its own and can be changed however you like.
Crockford has quite a good chapter on this subject in The Good Parts.
In it he points out one big flaw with using
new
on constructor functions:(You may already be aware of this, hence your question, but it's worth reiterating)
His proposed solution is to recommend a home rolled
Object.create
(The Good Parts predates ES5 by a bit, but the idea is the same as the native version mentioned in the other answers).Object.create
takes an instance of an object to use as the prototype and returns an instance.The example used is very similar to your "something like this" example (except Crocky uses mammals and cats instead of cars and buses):
One approach - create a Car and use Object.create to make a copy and then extend Bus functionality as needed
Object.create
gets you the behavior that you are looking for, but you have to call it instead ofnew
:Alternatively, you can use the new ES 2015's
__proto__
property to set the prototype at declaration time:Some additional notes
You should add the methods to
Car.prototype
not inside of the constructor unless you need the private state (this way there is only one instance of thesetModel
method, rather than one instance of the method per instance of the class):You can get around the
new Car
oddness withObject.create
even with constructor functions:To use an instance as prototype in order to inherit shows a lack of understanding what prototype is. Prototype shares members and a mutable instance member of Parent on the prototype of Child gets you very unexpected behavior. Setting Car.prototype to Object.create(Bus.prototype) has already covered by others, if you want to see the role of the constructor and the role of the prototype maybe the following answer can help: https://stackoverflow.com/a/16063711/1641941
To demonstrate what could go wrong let's introduce an instance specific mutable member called
passengers
we would like Bus to initialize this so we can't use Jeff's example as that only takes care of the prototype part. Let's use constructor functions but create an instance of Bus for Car.prototype.This error could be resolved by shadowing instance properties by re using Parent constructor (Bus.call(this... as provided later) but Car.prototype still has a passengers member that has no business being there.
If you want to protect agains people forgetting "new" you can do the following:
You can use
Object.create()
to achieve. Here is a crude example of prototypal inheritance using this :