JavaScript OOP - the smart way

Prototype JavaScript library has had OOP for years, but their solution is very ugly. In this post I will describe a new elegant way of doing JavaScript OOP. My solution is heavily inspired by mootools.

AJS 3.5 is out and it includes this OOP scheme.

What we will implement:

JavaScript OOP d1

The Person class

We create a base class called Person:

Person = new AJS.Class({
    init: function(name) {
        this.name = name;
        Person.count++;
    },
    getName: function() {
        return this.name;
    }
});
Person.count = 0;

Notice that we have an init function, this is the class constructor and it will be called automatically when an instance is created. count is a static field.

UniversityPerson class

UniversityPerson extends the Person class:

UniversityPerson = Person.extend({
    init: function(name, school) {
        this.parent(name);
        this.school = school;
    },
    getSchool: function() {
        return this.school;
    }
});

Notice the this.parent call - it's used to call parent's constructor.

Student and Professor classes

Both classes extend UniversityPerson, and we write that following way:

Student = UniversityPerson.extend({
    init: function(name, school, id) {
        this.parent(name, school);
        this.student_id = id;
    },
    getStudentId: function() {
        return this.student_id;
    }
});

Professor = UniversityPerson.extend({
    init: function(name, school, cls) {
        this.parent(name, school);
        this.cls = cls;
    },
    getClass: function() {
        return this.cls;
    },
    getName: function() {
        return 'Professor ' + this.parent();
    }
});

We again use this.parent inside init function to call the parent's constructor. Notice that you also from getName can use this.parent, this will then call this.parent.getName - quite useful!

Creating instances

Creating some objects is really easy:

var amir = new Student('Amir', 'Aarhus University', 1);
var benny = new Student('Benny', 'Parrot University', 2);
alert(amir.getName()); //Amir
alert(benny.getStudentId()); //2

var johhny = new Professor('Johhny', 'JA University', 'Jack ass');
alert(johhny.getClass()); //Jack ass
alert(johhny.getName()); //Professor Johhny

GreyBox 5

I used this approach in GreyBox 5 and I am quite satisfied with the usage.

GreyBox 5 class diagram looks like this:

JavaScript OOP d2

Implementaion

The implementation is only around 35 lines of code:

AJS.Class = function(members) {
    var fn = function() {
        if(arguments[0] != 'no_init') {
            return this.init.apply(this, arguments);
        }
    }
    fn.prototype = members;
    AJS.update(fn, AJS.Class.prototype);
    return fn;
}

AJS.Class.prototype = {
    extend: function(members) {
        var parent = new this('no_init');
        for(k in members) {
            var prev = parent[k];
            var cur = members[k];
            if (prev && prev != cur && typeof cur == 'function') {
                cur = this._parentize(cur, prev);
            }
            parent[k] = cur;
        }
        return new AJS.Class(parent);
    },

    implement: function(members) {
        AJS.update(this.prototype, members);
    },

    _parentize: function(cur, prev) {
        return function(){
            this.parent = prev;
            return cur.apply(this, arguments);
        }
    }
}
Announcements · Code · JavaScript 25. Nov 2006
11 comments so far

amir - since there are tons OO of js libraries popping out everywhere on the web it'd be cool if you could put a blurb on what makes AJS different from other, say mootools.

axolx:
mootools is related to Prototype and they extend almost everything in JavaScript. AJS uses the functional approach - nothing is extended, but functions are used instead.

For example, take the bind function, in AJS you would write:

var new_fn = AJS.$b(fn, some_object);

In mootools or Prototype you would write:

var new_fn = fn.bind(some_object);

The functional approach is also a lot cleaner since it does not pollute the global scope. For example, it could give some bugs if you use mootools and Prototype on the same page.

I was hoping you could answer as to where I can find the detailed information on OOP in Javascript?

I am trying to find information on OOP in Javascript - however I only get information what built in objects are and how to create basic user defined objects.

Thanks.

Raj:
Try to search on Google after javascript prototype - there are lots of good reading there.

Class-based javascript

Animal = new AJS.Class({
  init: function(name) {
    this.name = name;
  }
});

amoeba = new Animal('Greenie');

Dog = Animal.extend({
  bark: function() {
    return this.name + " says woof!";
  }
});

lassie = new Dog('Lassie');
alert(lassie.bark()); // Lassie says woof!

Prototype-based javascript (Concatenation)

Animal = clone({}, {}, {});
amoeba = clone(Animal, {name: 'Greenie'}, {});

Dog = clone(Animal, {}, {bark: 'this.name + " says woof!"'});

lassie = clone(Dog, {name: 'Lassie'}, {});
alert(lassie.bark()); // Lassie says woof!

//

function clone(myObj, members, gets){
  if(typeof(myObj) != 'object') return myObj;
  if(myObj == null) return myObj;
  var myNewObj = new Object();
  for(var i in myObj) myNewObj[i] = clone(myObj[i]);
  for(var i in members) myNewObj[i] = clone(members[i]);
  for(var i in gets) myNewObj[i] = new Function("return " + gets[i]);
  return myNewObj;
}

XCSADASDASDF

CCCCCCCCCCCCCCCCCCC

Amir, I'd like to know if I may use a modified version of your AJS.Class (I removed implement and _parentize) in a GPL 2.0 project I'm working at. Of course giving you the credit for, along with the MIT license and a hyperlink to AJS.

I may send you the source if you wish.

See ya,

Luis

I may send you the source if you wish.

Calling this.parent() in the context of subclass override is nice and it's not explicit which might confuse the casual programmer or newbie.

I am trying to find information on OOP in Javascript - however I only get information what built in objects are and how to create basic user defined objects.
-----------------------------------------------------------
Health Dissertation | Finance Dissertation

Post a comment
Commenting on this post has expired.
© 2000-2009 amix. Powered by Skeletonz.