Reputation: 15034
// Prototye Inheritance
var AnswerPrototype = {
constructor: function(value){
this._val = value;
},
get: function(){
return this._val;
}
}
var lifeAnswer = Object.create(AnswerPrototype);
lifeAnswer.constructor(100);
alert(lifeAnswer.get());
var desertAnswer = Object.create(AnswerPrototype);
desertAnswer.constructor(200);
alert(desertAnswer.get());
var firmAnswerProtoype = Object.create(AnswerPrototype);
firmAnswerProtoype.get = function(){
return AnswerPrototype.get.call(this);
}
var luckyAnswer = Object.create(firmAnswerProtoype);
luckyAnswer.constructor(1);
alert(luckyAnswer.get());
var magicAnswer = Object.create(firmAnswerProtoype);
magicAnswer.constructor(2);
alert(magicAnswer.get());
// Classical Inheritance
function Answer(value){
this._val = value;
}
Answer.prototype.get = function(){
return this._val;
}
var lifeAnswer = new Answer(100);
alert(lifeAnswer.get());
var desertAnswer = new Answer(200);
alert(desertAnswer.get());
function firmAnswer(value){
return Answer.call(this,value);
}
firmAnswer.prototype = Object.create(Answer);
firmAnswer.prototype.constructor = firmAnswer;
firmAnswer.prototype.get = function(){
return Answer.prototype.get.call(this);
}
var luckyAnswer = new firmAnswer(20);
alert(luckyAnswer.get())
Can anyone tell me on how the second one is classical and the first one is prototypal. I was watching the http://www.objectplayground.com/ and i am totally confused as in both the cases we use Object.create()
and as well as prototype
object.
Upvotes: 3
Views: 197
Reputation: 664246
How is the second one is classical and the first one is prototypal
Both are using prototypical inheritance, there are no classes in JavaScript.
The second one is called "classical" (sometimes "pseudoclassical") because it uses the class pattern and mimics the conventional class syntax (as known from Java) when objects are created with the new
operator.
The only difference is the .prototype
link from the constructor function to the prototype object and the shorter instantiation syntax with only one command instead of two, what happens behind is the same in both approaches.
As we can see in your example, also the inheritance between two "classes" is a bit different. In both approaches the child prototype object inherits from the parent prototype object, and in both approaches you can call parent ("super") methods by invoking the functions explicitly on the child instance. Yet, in the "classical" pattern you need to declare a new constructor function for the child (to reference it), while in your explicit prototypical approach the children are inheriting the parent's .constructor
method.
Upvotes: 1
Reputation: 2179
First, to get it straight, Javascript only has prototypal inheritance. What you can do is simulate "classical" inheritance. The difference between the two boils down to the syntax with which objects are instantiated - "classical" inheritance uses the more familiar constructor functions and "new" operator, which hide the inherent prototypal nature of Javascript's object creation and inheritance properties.
Let's break down both cases a bit.
var AnswerPrototype = {
constructor: function(value){
this._val = value;
},
get: function(){
return this._val;
}
}
The prototype here is explicitly created, along with a "constructor" (or more properly named, initializing function).
var lifeAnswer = Object.create(AnswerPrototype);
lifeAnswer.constructor(100);
alert(lifeAnswer.get());
Now, creating objects is slightly clunky here. First you need to call Object.create(), and then you need to call the initializer function. This doesn't have to be the case though - here's a different sample prototype which does both in one swoop:
var AnswerPrototype = {
create: function(value){
var obj = Object.create(AnswerPrototype);
obj._val = value;
return obj;
},
get: function(){
return this._val;
}
}
var lifeAnswer = AnswerPrototype.create(100);
Simulating "classical" inheritance relies on letting developers use the more familiar constructor functions and "new" operator to create their objects, but since it it just masking the prototypal inheritance of Javascript, it remains essentially the same thing.
function Answer(value){
this._val = value;
}
Answer.prototype.get = function(){
return this._val;
}
This isn't much different from the prototypal inheritance one, except the Answer is decoupled from the now implicitly created prototype object(Which can be accessed via the Answer.prototype property)
var lifeAnswer = new Answer(100);
Practically, sugar for var lifeAnswer = Object.create(Answer.prototype); // Call Answer on the newly created object to initialize some values, e.g. with Answer.call(lifeAnswer, 100);
firmAnswer.prototype = Object.create(Answer);
firmAnswer.prototype.constructor = firmAnswer;
firmAnswer.prototype is just the implicitly created prototype, very similar to firmAnswerPrototype in the first case.
To answer your specific question, the reason why they use Object.create() here is because inheritance via new
quickly becomes very clunky. You would need to do something like:
firmAnswer.prototype = new Answer();
But now you either need Answer
to be an empty constructor(function Answer() {}
), or explicitly differentiate between calling it with no arguments(to use for inheritance), and calling it with arguments(to use for instantiating "Answer" objects).
Upvotes: 2
Reputation: 37369
You have those backwards. The second one is prototypal because it uses the object's prototype
property to inherit. This block
firmAnswer.prototype = Object.create(Answer);
firmAnswer.prototype.constructor = firmAnswer;
firmAnswer.prototype.get = function(){
return Answer.prototype.get.call(this);
}
is assigning an instance of Answer
to firmAnswer
's prototype. However, it's piss poor code, as it's not actually taking advantage of the inheritance, it's redeclaring the get
function.
I would avoid this code altogether. Read Crockford's The Good Parts for a good distinction between the two types.
EDIT: To give a bit of an explanation (without referencing that code), here's the basic difference.
'Classical' inheritance in Javascript (the way I see it used) is when you override objects properties. You have an object with a foo
and a bar
method. You then use a library (like jQuery or Prototype) to call an extend
method. The method takes two arguments, a base object and a child object. It takes all of the properties of the base object, inserts the properties of the child object (possibly overwriting) and then returns a new object that has a mix of both properties. There's a bit more to it, but that's the gist. It's just manipulating object properties without the prototype.
Prototypal inheritance uses Javascript's built in prototype. A prototype is a chain of objects (essentially). Let's say you have an object B that inherits from A. To create a C class that inherits from B, we create a function named C and then assign B to the prototype. Then, when a property is requested from C, Javascript will do the following:
Check if the property exists on the instance of C. If not:
Check if the property is on the prototype of B. If not:
Check if the property is on the prototype of A. If not:
Throw error.
Sorry if it's a little vague. I'm trying to simplify it a bit. There's a lot to the prototype in Javascript. I would suggest reading some of Crockford's materials.
Upvotes: 1