Reputation: 11533
I am new to JavaScript (started learning it this week). I've completed the CodeCademy course (actually just Objects 1 && 2 parts, rest was boring). I thought I learned prototypal inheritance with constructors, but than I've started watching Douglas Crockford: Advanced JavaScript
Right at the beginning of the video, he mentions 2 types of inheritance, and I've realized, everything I thought I knew, I don't know. So I've started playing with Chrome JavaScript console and tried to do something using both inheritance models.
//create constructor
function MyParent(){
this.name = "joe";
this.sayHi = function(){
console.log(this.name);
}
}
//create child object and inherit from parent
var myChild1 = new MyParent();
myChild1.name
"joe"
myChild1.sayHi()
joe
//add method to MyParent, so it can be accessed from myChild1
MyParent.prototype.sayBye = function(){ console.log("bye");}
myChild1.sayBye()
bye
//create another constructor
function MyParent2(){
this.sayHi = function(){
console.log("hi");
}
}
//make it inherit from MyParent, overwriting sayHi if object is instance of MyParent2
MyParent2.prototype = new MyParent();
//overwrote sayHi
var myChild11 = new MyParent2();
myChild11.sayHi();
hi
//still same as MyParent as its not overwriten in MyParent2
myChild11.name
"joe"
Than I've tried to do the same thing using Object.create:
//create an object
var myParent = {
name : "joe",
sayHi : function(){
console.log(this.name)
}
};
//it works
myParent.sayHi()
joe
//create child object
var myChild = Object.create(myParent);
myChild.sayHi()
joe
//add bye method to myChild
myChild.sayBye = function(){ console.log("bye"); }
myChild.sayBye();
bye
//add bye method to myParent - does not overwrite child's bye
myParent.sayBye = function(){ console.log("bye2"); }
//however adding sayBye2 to parent, becomes available on already created child
myParent.sayBye2 = function(){ console.log("bye2"); }
myChild.sayBye2();
bye2
//but its the parent property
myChild.hasOwnProperty("sayBye2")
false
//could make million objects inherit from each other vertically or horizontally
var myChild2 = Object.create(myChild);
myChild2.name
"joe"
So far, just by first impression, I do like both models, maybe I slightly prefer the latter. It seems to be more expressive and powerful.
I've done some search on the vs.
topic, but couldn't find a good article, that would explain pros and cons of each approach (other than latter is supported by newer browsers only, but there is a simple workaround). Rest of the posts I found were just tl: dr; and somewhat boring.
So my question is, which type of inheritance should I go with. Are there any perks associated with either? Any major cons for either? Can you mixin both? (eg. I know you can pass object as argument into new Constructor()
))
Thanks
EDIT: Looking at trick to create Object.create() alternative if browser doesn't support it, I realized how simple the hack is. It is basically creating an empty constructor, assigning parent object as its prototype and returning the built constructor as new object. What a neat hack!
if(typeof Object.create !== "function") { Object.create = function (o) { function F() {}; F.prototype = o; return new F(); }; }
But what are the implications? Any gotchas to be aware of?
Upvotes: 3
Views: 683
Reputation: 43718
Both ways are equally powerful. Some says that you are not a real JavaScript master if you do not embrace the pure prototypal approach, but really everything is still just prototypal inheritance and it's a matter of style.
Personnaly, I prefer using a classical approach and make use of the new
keyword together with a constructor
function.
Why?
init
function on my objects only to do what a constructor
does already. As you probably noticed, the pure prototypal approach leaves you without a constructor
so you will have to implement an initialization function (generally called init
) if you need to run some initialization logic for newly created objects.However, I find that the pure prototypal approach is a bit less verbose and might be easier to understand for programmers without a strong background with languages implementing classical inheritance.
By the way, one thing you should avoid with the classical model is to inherit using the new
keyword like you are doing above because you are running the parent constructor
logic unnecessary and it could potentially have undesirable side-effects.
You should be using Object.create
like below:
function A(val) { this.val = val; }
A.prototype.alertVal = function () { alert(this.val); };
function B(val) {
A.call(this, val); //call parent constructor
}
B.prototype = Object.create(A.prototype); //inherit from A
var b = new B('test');
b.alertVal(); //test
At the end, it's all a matter of taste and I respect both ways. Maybe someone else will want to improve this answer with some real advantages/disadvantages, but I cannot find any.
Upvotes: 3
Reputation: 2594
Constructing objects with new
was pronounced evil, because you can forget to use it and then whatever properties you add to this
will end up added to the global object. For this reason I am in for the second approach.
One other thing I have learnt is that you should not try to apply "classical" OOD to JavaScript. It has its own way that should be understood and it is quite nice in fact. I think most of object programming problems in JavaScript come from attempts to stretch notion of "class" onto JavaScript.
Upvotes: 0