IT:AD:JScript:OOP
About
Javascript is a bizarre little fighter language that somehow survived … in the same way that DuctTape survives. Not really perfect, but can used for many things…
Classes
OOP is basically a class definition with member methods and properties.
Unfortunately, there is no class keyword in Javascript…But you can use function to get to the same point.
How it's done is create a function, using the name of the 'class', and make it the Constructor.
Prototypes
[TODO]
Constructors
Example:
function MyClass() {
}
In it, you can use the this keyword:
function MyClass(id) {
//save the passed constructor arg as a var internal to
//the function...which is going to be the class...
this.id = id;
}
Methods
JScript is hugely flexible, and allows you to attach methods to something. In this case, we can use this to our advantage by attaching new methods to the Prototype of the class:
function MyClass(id) {
this.id = id;
}
MyClass.prototype.myMethod = function(someText) {
//we can use the this keyword to get back
//to vars defined in the Constructor:
var theId = this.id;
//And use it anyway you want. In this case,
//some trivial JQuery:
$(theId).html(someText);
}
That's it! Constructors, Class scoped vars, and Methods! What else do you want?!?!
Properties
Oh… Properties. There are none in JScript. But one can wrap fields the same way as in Java:
function MyClass(id) {
this.id = id;
}
MyClass.prototype.myMethod = function(someText) {
var theId = this.id;
$(theId).html(someText);
}
MyClass.prototype.setId= function(id) {
//do some arg checking...
//...
//then set the var
this.id = id;
}
MyClass.prototype.getId= function() {
return this.id;
}
I'm personally not so keen on properties, but when there is a need for them…
This
One last point. …the this keyword.
There is one hitch…The this keyword is dynamically parsed at runtime…which is a useful thing in a lot of cases…and a gotcha when dealing with OOP in Javascript.
For example:
if you create an Event handler in a class, and bind to it a class property:
function MyClass(id) {
this.id = id;
this.init();
}
MyClass.prototype.init=function() {
$('#' + id).click( function() { this.ourEventHandler(); }
}
MyClass.prototype.ourEventHandler = function() {
$(theId).html("BANG!");
}
… it will fail. The reason is that when it parses this.ourEventHandler() it will dynamically process the word this at runtime, and this will be parsed as the context it is in (the event), not when it was defined (the class).
This is weird…but easily worked around. Use a proxy var…
function MyClass(id) {
this.id = id;
this.Init();
}
MyClass.prototype.Init() {
var oC;
$('#' + id).click( function() { oC.ourEventHandler(); }
}
MyClass.prototype.ourEventHandler = function() {
$(theId).html("BANG!");
}
Now it will proccess oC, which is still holding the var that it was filled with.
Closure Definitions
Sometimes you don't want to create a whole prototype based structure, just to define it once (eg: for a stateless Service of some kind).
First, I'll ask you if you really want to skip that – it really saves little time, and limits future changes, but whatever…
The way to Create a class in one go, with no prototype is:
Ext.ns('myApp.mynamespace');
myApp.mynamespace.myService =
(
function(){
var instance = {};
instance.myVar = "ABC";
//ShortHand way of attaching a method
instance.getMyVar = function (){
return this.myVar;
}
return instance;
}
)();//run function, that factories up 'instance', and returns it.
//from now on, you can access the service as follows:
var x = myApp.mySpace.myService.getMyVar();
Final Notes
For the purists… UpperCase function names are reserved for constructors, so SomeMethod should be someMethod.
I always forget that…