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:
The Person classWe 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 classUniversityPerson 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 classesBoth 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 instancesCreating 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 5I used this approach in GreyBox 5 and I am quite satisfied with the usage. GreyBox 5 class diagram looks like this:
ImplementaionThe 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
|
|