« Back to Index

Example of prototypal inheritance but done in a ‘classical inheritance’ style…

View original Gist on GitHub

prototype.js

/*
    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();