How to write Object Oriented javascript ?
I explain simple steps to convert your plain javascript code to an object oriented javascript code.
1.) I will guide you to start with a simple function to the object oriented function at last.
2.) How to do multiple inheritance like in C++, Multi level inheritance like in Java
3.) Friend function like C++
4.) what do you mean by Redefinition in Javascript?
5.) How to design package ?
6.) how to use __proto__, instanceof ?
7.) Singleton design pattern
8.) Enum function
9.) what is prototype.constructor and when to use it ?
step-1: Look at this simple Function.
function add(a, b) {
return a + b;
}
function sub(a, b) {
return a – b;
}
var sum = add(2, 3);
var diff = sub(2, 3);
step-2: Another way by anonymous function
var add = function(a, b) {
return a + b;
}
var sub = function(a, b) {
return a – b;
}
var sum = add(2, 3);
var diff = sub(2, 3);
step-3: By anonymous function, executing it immediately
var sum = function(a, b) {
return a + b;
} (2, 3);
var diff = function(a, b) {
return a – b;
} (2, 3);
step-4: By Object level functions
var math = new Object();
math.add = function(a, b) {
return a + b;
}
math.sub = function(a, b) {
return a – b;
}
var sum = math.add(2, 3);
var diff = math.sub(2, 3);
//or
var sum = math[“add”](2, 3);
var diff = math[“sub”](2, 3);
step-5: By Function Map
var math = {
“add” : function(a, b) {
return a + b;
},
“sub”: function(a, b) {
return a – b;
}
};
var sum = math[“add”](2, 3);
var diff = math[“sub”](2, 3);
//or
var sum = math.add(2, 3);
var diff = math.sub(2, 3);
step-6: Now look at how to make it much more object oriented
function Math() {
this.add = function(a, b) {
return a + b;
};
this.sub = function(a, b) {
return a – b;
};
return this;
}
var math = new Math();
var sum = math.add(2, 3);
var diff = math.sub(2, 3);
//or
var sum = math[“add”](2, 3);
var diff = math[“sub”](2, 3);
//drawback: You cannot redefine the member functions commonly
step-7: Now, i am introducing 'prototype', prototype is like a map which holds the the object member definition of any Function
function Math() {
return this;
}
Math.prototype.add = function(a, b) {
return a + b;
}
Math.prototype.sub = function(a, b) {
return a – b;
}
var math = new Math();
var sum = math.add(2, 3);
var diff = math.sub(2, 3);
//or
var sum = math[“add”](2, 3);
var diff = math[“sub”](2, 3);
Note: ‘prototype’ is present inbuilt in all normal function
step-8: Another way of implementing it as like a map
function Math() {
return this;
}
Math.prototype = {
add: function(a, b) {
return a + b;
},
sub: function(a, b) {
return a – b;
}
};
var math = new Math();
var sum = math.add(2, 3);
var diff = math.sub(2, 3);
//or
var sum = math[“add”](2, 3);
var diff = math[“sub”](2, 3);
step-9: By anonymous prototype functions
var Math = function() {
return this;
}
Math.prototype = {} //Note: ‘prototype’ is not present in anonymous function
Math.prototype.add = function(a, b) {
return a + b;
}
Math.prototype.sub = function(a, b) {
return a – b;
}
var math = new Math();
var sum = math.add(2, 3);
var diff = math.sub(2, 3);
//or
var sum = math[“add”](2, 3);
var diff = math[“sub”](2, 3);
Inheritance : Look at this example
function Address() {
return this;
}
Address.prototype.setStreet = function(_street) { this.street = _street; }
Address.prototype.getStreet = function() { return this.street; }
Address.prototype.setCity = function(_city) { this.city = _city; }
Address.prototype.getCity = function() { return this.city;}
function Person() {
return this;
}
Person.prototype = new Address();
function Employee() {
return this;
}
Employee.prototype = new Person();
Employee.prototype = new Account(); //this throws error
Drawback: cannot do multiple inheritance like C++
Lets see how to do it, this is what most of the javascript library is doing,
‘extend’
function extend(childclass, parentclass) {
var _clazz = function() { };
_clazz.prototype = parentclass.prototype;
childclass.prototype = new _clazz();
childclass.prototype.constructor = childclass;
childclass.super = parentclass.prototype;
}
function Person() {
return this;
}
function Address() {
return this;
}
function Employee() {
return this;
}
extend(Employee, Person);
extend(Employee, Address);
Now you need to understand 'instanceof' and '__proto__'
Instanceof : It works like java instanceof
var emp = new Employee();
emp instanceof Employee // returns true
__proto__: It is used to call super class method
function Shape() {
return this;
}
Shape.prototype.draw = function() { …}
function Square() {
return this;
}
Square.prototype = new Shape();
Square.prototype.draw = function() { this.__proto__.draw(); … }
function Cube() {
return this;
}
Cube.prototype = new Square();
Cube.prototype.draw = function() {
this.__proto__.draw();
//.....
}
var c = new Cube();
c.__proto__.draw(); //calls the Square’s draw function
c.__proto__.__proto__.draw(); //calls the Shape’s draw function
What is redefinition ?
Redefinition: Like java invocation handler
function Circle() {
return this;
}
Circle.prototype.draw = function(g) {
g.paint(“circle”, this);
}
var _circle_draw_func = Circle.prototype.draw;
Circle.prototype.draw = function(g) {
//do before ….
_circle_draw_func.call(this, g); //This is like friend function in C++
//do after ….
}
If you don’t do it like this, then you will be replacing the original function with your new function definition
How to construct package ?
if(typeof(com) != “undefined”) {
throw “package ‘com’ is already defined”
}
var com = {};
if(typeof(com.tejas) != “undefined”) {
throw “package ‘com.tejas’ is already defined”
}
com.tejas = {};
if(typeof(com.tejas.lang) != “undefined”) {
throw “package ‘com.tejas.lang’ is already defined”
}
com.tejas.lang = {};
note: you should throw error, otherwise all your definitions on first js file will be replaced by the second js file if both using same packages
Creating function definition on package
com.tejas.web.js.Circuit = new function() {
this.sncs = [];
return this;
}
com.tejas.web.js.Circuit.prototype = { }
com.tejas.web.js.Circuit.prototype.addSncs = function(snc) {
this.sncs.push(snc);
}
Note: Anonymous functions will not have ‘prototype’ map by default.
how to implement Design patterns ?
Singleton
var shapeFactory = function() {
this.createCircle = function() {
return new Circle();
};
this.createSquare = function() {
return new Square();
};
} ();
//but if you need it to be a child of some other function
var shapeFactory;
function ShapeFactory() {
if(!shapeFactory) {
shapeFactory = this;
}
return shapeFactory;
}
ShapeFactory.prototype.createCircle = function() { return new Circle(); }
ShapeFactory.prototype.createSquare = function() { return new Square(); }
How to derive Enum ?
Enum: You have to define it like a singleton object …
com.tejas.lang.TimeUnit = function() {
if(!com.tejas.lang.TIMEUNIT) {
com.tejas.lang.TIMEUNIT = this;
}
return com.tejas.lang.TIMEUNIT;
}
com.tejas.lang.TimeUnit.prototype = {}
com.tejas.lang.TimeUnit.prototype.WEEK = new _TimeUnit(7 * 24 * 60 * 60 * 1000);
com.tejas.lang.TimeUnit.prototype.DAY = new _TimeUnit(24 * 60 * 60 * 1000);
com.tejas.lang.TimeUnit.prototype.HOUR = new _TimeUnit(60 * 60 * 1000);
com.tejas.lang.TimeUnit.prototype.MIN = new _TimeUnit(60 * 1000);
com.tejas.lang.TimeUnit.prototype.SECONDS = new _TimeUnit(1000);
function _TimeUnit(_inSeconds) {
this.seconds = _inSeconds;
return this;
}
_TimeUnit.prototype.convert = function(milli_seconds) { ….. }
new com.tejas.lang.TimeUnit(); //Using: var x = com.tejas.lang.TIMEUNIT.HOUR.seconds;
Constructor
It is a built-in property of the ‘prototype’
Ex: Employee.prototype.constructor
It actually has the reference of the constructing function of the Function
var emp = new Employee.prototype.constructor(); is same like
var emp = new Employee();
Usage: It is used like java reflection kind of feature
Thanks for reading this ....
No comments:
Post a Comment