JavaScript: Not your father's inheritance model - Part 2
This post is part of a series called JavaScript Demystified.

This particular chapter is further divided in two parts. Read Part 1.

Build your own hierarchy

Let's pretend we are building some scripts that deal with musical instruments. We could define our own Guitar class type like this:

//The constructor
function Guitar(brand, model) {
    this.brand = brand;
    this.model = model;
    this.strings = ['E', 'A', 'D', 'G', 'B', 'e'];
}

//Instance methods
Guitar.prototype = {
    play: function (chord) {
        alert('Playing ' + chord); 
    },
    toString: function () {
        return '(Guitar: ' + 
            this.brand + ' ' +
            this.model + ')';
    }
};

var guitar1 = new Guitar('Gibson', 'Les Paul');

What may not be apparent by just looking at the code for the first time is that guitar1's Prototype will be Guitar.prototype, which means that guitar1 inherits from Guitar.prototype. Also guitar1.constructor === Guitar.

When the last line in the above example is executed, the JavaScript runtime will take care of initializing a new object that has Guitar.prototype as its Prototype and makes its constructor property point to the Guitar function.

But what if we want to create a different type of guitars and still reuse the existing Guitar type. We could do this:

function BassGuitar(brand, model) {
    //call the constructor of our base type
    Guitar.apply(this, [brand, model] );
    //change or add anything we wish
    this.strings = ['E', 'A', 'D', 'G'];
}

//Copy the Prototype of our base type
BassGuitar.prototype = Object.create(Guitar.prototype);

//Override whatever we want:
BassGuitar.prototype.toString = function () {
    return '(BassGuitar: ' + 
        this.brand + ' ' +
        this.model + ')';
};

var bass1 = new BassGuitar('Peavey', 'Cirrus');
bass1.toString(); //=> '(BassGuitar: Peavey Cirrus)'
alert(bass1.strings); //=> [ 'E', 'A', 'D', 'G' ]

But there's a problem with the above code. There isn't a method Object.create(). Yeah, that's one of the design omissions in JavaScript. Any prototype-based language needs an easy way to let use create objects from other objects.

Thankfully JavaScript is also dynamically typed, so we can add that function ourselves. Here I'm borrowing from Douglas Crockford.

//add this to the very beginning of your scripts
if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

I'll leave the interpretation of the above function as an exercise to the reader. Once you understand what it is doing you will have mastered prototypes and constructors.

Handy Prototype tricks

Knowing what we know now and once again leveraging JavaScript's dynamism we can fix one of the things that has always annoyed me in JavaScript: the lack of a trim() method on strings.

String.prototype.trim = function () {
    return this.replace( /^\s*(\S*(\s+\S+)*)\s*$/, "$1"); 
}; 
var text = ' some user-entered value   ';
alert( text.trim() ); // => 'some user-entered value'

How about an easy way to pad numbers with zeroes?

Number.prototype.padLeft = function (width) {
    var text = this.toString();
    for(; text.length < width; ){
        text = '0' + text;
    }
    return text;
};

var num = 1234;
alert(num.padLeft(6)); // => 001234

Why do I need to know all this stuff?

Well, you don't. But why even bother writing JavaScript code if you're not willing to learn how it works?

As we have been seeing during this series, JavaScript bears only some syntax similarities with C# or Java. Underneath the surface it has been designed very differently. The web is riddled with attempts to mimic class-based inheritance in JavaScript only because programmers don't want to learn and leverage prototype-based logic.

My humble advice is that you will feel happier and smarter if you chose to learn how to use the language as it was intended.


Posted 06-12-2009 6:26 PM by sergiopereira

[Advertisement]

Comments

DotNetShoutout wrote JavaScript: Not your father's inheritance model - Part 2 - Sergio Pereira - Devlicio.us
on 06-13-2009 12:17 AM

Thank you for submitting this cool story - Trackback from DotNetShoutout

Simon wrote re: JavaScript: Not your father's inheritance model - Part 2
on 06-14-2009 6:34 PM

Thanks for this great series... I'm a C++/C# programmer for 15 years and am just now getting into JavaScript. This series has really been informative and I feel much more comfortable knowing how some of the language foundations work.

FYI, your first example under Handy Prototype Tricks has a typo... rather than "alert(text);" , shouldn't it be "alert(text.trim());"?

sergiopereira wrote re: JavaScript: Not your father's inheritance model - Part 2
on 06-14-2009 8:42 PM

@Simon, thanks for the feedback and for pointing out that typo. I've just fixed it.

on 06-15-2009 10:31 AM

WF/Orcas Sequential and Flowchart modeling styles Introduction to Workflow Tracking in .NET 4.0 Beta 1 Building Applications for Orcas - With the "Oslo" May 09 CTP, the MSDN Library now contains a number of additional topics covering more of

Eduardo Scoz wrote re: JavaScript: Not your father's inheritance model - Part 2
on 06-15-2009 11:47 PM

Very cool series, Sergio! Congrats.

Ellison wrote re: JavaScript: Not your father's inheritance model - Part 2
on 08-31-2010 3:31 PM

Article quote:

"I'll leave the interpretation of the above function as an exercise to the reader. Once you understand what it is doing you will have mastered prototypes and constructors. "

Why not just explain what it's doing and why? Leaving it unexplained feels like it goes against the "demystifying" attitude that the rest of the series lives up to.

sergiopereira wrote re: JavaScript: Not your father's inheritance model - Part 2
on 08-31-2010 5:13 PM

@Ellison,

I really believe it's a worthy exercise. There's nothing mythical in that function once you understand the previous concepts in the article.

I'm only trying to explain prototypal inheritance so taking a paragraph or two to explain that function could be distracting.

If you still find it unclear, hit me up on the Contact link at the top and I'd be more than happy to provide you the explanation.

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)