/*
The following style of inheritance is called 'classical inheritance'
The fundamentals of it are using functions as a 'Constructor' (class) to create new objects.
*/
function Article(title, date, description) {
this.title = title || 'No title provided';
this.date = date || 'No date provided';
this.description = description || 'No description provided';
}
/*
Notice we didn't do...
function Article(title, date, description) {
...
this.displayArticle = function(){};
}
...instead we set the `displayArticle` method directly onto the `prototype` of the `Article` constructor.
The reason we do this is because it results in better performance.
The reason why this is better performing is because if we put `displayArticle` inside the constructor function
then every new instance/object we created would have a copy of `displayArticle` within it. But by setting it on
the prototype chain it means there is only ever one instance of the `displayArticle` method and all instances/objects
created refer to that one function.
*/
Article.prototype.displayArticle = function() {
console.group(this.title);
console.log('Article date: %s | Article description: %s', this.date, this.description);
console.groupEnd();
};
/*
If you want to create sub classes that inherit functionality from the base class (in this case `Article`)
then there are at least 10 different ways to do it.
The most typical pattern is this...
function inherit(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
// Only this (i.e. creating new instance of intermediate constructor F) maintains the prototype chain.
// But also allows us to add to Child.prototype without affecting the parent.
Child.prototype = new F();
Child.uber = Parent.prototype;
Child.prototype.constructor = Child;
}
inherit(SubArticle, Article);
...but an even simpler way to do inheritance is like so...
*/
function SubArticle(title, date, description, links) {
// We're executing the parent constructor (Article) and passing through the details to it but
// using SubArticle as the context
Article.call(this, title, date, description);
// New data that has nothing to do with Article and is specific to SubArticle
this.links = links || 'No links provided';
}
// The following line lets the 'SubArticle' Class inherit all 'Article' methods/properties set on the Article prototype chain
// Because we're only using `Article` to generate the prototype chain for us to assign to `SubArticle` we don't bother passing
// any arguments to the `new Article` and so we don't need the parenthesis at the end (e.g. we don't need to do this `new Article()`)
// That goes for any constructor in JavaScript: e.g. `new Date()` can be written as `new Date` without parenthesis.
SubArticle.prototype = new Article;
SubArticle.prototype.displayLinks = function() {
console.log(this.links);
}
var main = new Article('My main Title', '2013-03-05', 'My main description');
main.displayArticle();
try {
main.displayLinks();
} catch(e) {
alert("The previous line of code just failed because I'm trying to access a method that isn't available on the prototype chain for `Article` -> but it does exist for `SubArticle`");
}
// Now we can see that if we create a new `SubArticle` that we have access to the `displayArticle` method as well as any new
// methods we've created specifically for `SubArticle`...
var sub = new SubArticle('My Sub Title', '2013-03-05', 'My sub description', ['http://www.google.com/', 'http://www.yahoo.com/']);
sub.displayArticle();
sub.displayLinks();