OOP in JavaScript

As tested, this works in WebKit browsers (including iPhone), Firefox, Chrome, and Opera. I've abonded all hope for IE.

I am writing this article to help save the sanity of other developers who may trying to program in an OOP fashion for JavaScript. The last two weeks I've been working with Object Oriented Programming inside of JavaScript (not a strong OOP language). When I learned OOP I was using C++ is hands down a stronger OOP langauge than JavaScript. However, I've gotten used to the features of strong OOP langauages and have found the lack of it in JS to be somewhat annoying as I have to write more code to accomplish the same chores.

I'm going to show you two examples.

Example One: This is simple, but limited OOP. It supports member and method inheritance, but does not maintain the integrity of the constructor:

Function.prototype.extend = function(class) {     
    this.prototype = new Class(); 
}

Feature of Example One: instanceof works correctly.

function MyClass() {}
MyClass.extends(ParentClass);
var o = new MyClass();
alert(o instanceof ParentClass); // true 
alert(o instanceof ParentsParentClass); // true 
alert(o instanceof Object); // true 
alert(o instanceof Number); // false

Example Two: Here's what I've come up with so far to try and keep the family constructor in tact. It may be rough around the edges, but it works for now. (Please comment / email if you have additions).

Function.prototype.extend = function(c) {
    var funcToStr = function(str) {
        str = String(str).substr(String(str).indexOf('\n') + 1);
        str = str.substr(0, str.lastIndexOf("}"));
        return str;
    }
    
    if(c.name != "Object") {
        var s = '\n';
        s += funcToStr(c.prototype._construct);
        s += funcToStr(this.prototype._construct);
        
        //alert('this.prototype._construct = function() {'+s+'}');
        eval('this.prototype._construct = function() {'+s+'}');
    }
    
    var old = this.prototype;
    
    for(var i in c.prototype) {
        if(i != "_construct") this.prototype[i] = c.prototype[i];
    }
    //this.prototype.super = c;
    this.prototype.constructor = old.constructor;
    
    this.prototype.toString = function() {
        return "[Object " + this.constructor.name + "]";
    }
}

Feature of Example Two: Super is run on every inherited pseudo-class.

function ParentClass() {
    this._construct();
}
ParentClass.prototype._construct = function() {
    this.parentFunc();
}
ParentClass.extend(Object);
ParentClass.prototype.parentFunc = function() {
    alert('parent func ran!');
};

function ChildClass() {
    this._construct();
}
ChildClass.prototype._construct = function() {
    //
}
ChildClass.extend(ParentClass);

var o = new ChildClass();
dump(o);

/*
alerts the following: 
parent func ran! 

follow up alert is: 
_construct() 
super() 
toString() 
parentFunc() 
*/

You'll see I use a function called "dump" the code of which is listed below:

function dump(obj, funcs) {
    if(funcs === undefined) funcs = true;
    
    var str = "";
    for(var i in obj) {
        try {
            if(obj[i] instanceof Function) {
                if(funcs) str += i + "()\n";
            } else {
                str += i + ": " + String(obj[i]).substr(0, 20) + "\n";
            }
        } catch(e) {}
    }
    alert(str);
}

Here are a few pages I found helpful during my research.

Douglas Crockford - Classical Inheritence in JavaScript
Chris Pietschmann - Javascript Prototypal Inheritance Explained in Simple Terms
Gavin Kistner - OOP in JS, Part 2 : Inheritance
John Resig - Simple JavaScript Inheritance

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <p> <pre>
  • Syntax highlight code surrounded by the {syntaxhighlighter SPEC}...{/syntaxhighlighter} tags, where SPEC is a Syntaxhighlighter options string or "class="OPTIONS" title="the title".
  • Lines and paragraphs break automatically.
  • E-Mail addresses are hidden with reCAPTCHA Mailhide.

More information about formatting options

CAPTCHA
Complete this form and then pat yourself on the back.