Friday, January 20, 2012

Using Closures in JavaScript for some cool OO stuff

Is JavaScript Object Oriented? The obvious answer you get is : “Yes it is”.  Why? “Well it supports objects”. What is an object in JavaScript?: “ An object is a function”. Well then with just a function how are you going to implement encapsulation and polymorphism?

In this post, I will explain how a particularly powerful feature of JavaScript, called Closures, can be used for bringing about encapsulation and polymorphism. In future posts, I will explain how other JavaScript concepts can be used for cooler OO stuff.

So to begin with, what is a closure? – Closure is nothing but a combination of both a function and the environment in which the function is created. In other words it combines some data, with some operations that can work on that data – does not this sound very similar to something in the OO world Smile

Syntactically closures can be identified as thus : if you find a “function” keyword inside a function ( object), in JavaScript code, then it is a closure.

Now, in the below code, I am providing a semi – practical example of how we can use closure to do encapsulation and polymorphism. I am encapsulating the whole concept of “Trainer” in a JavaScript object ( which is nothing but a function). Depending on the value set for the trainer type ( dog or cat)  and the training type ( jump or roll), it becomes a dog trainer or a cat trainer and trains the animal to jump or roll – based on the value of the environment variable it morphs into different types.

 

<script type="text/javascript">
var
dogTrainer;
var catTrainer;

$(document).ready(function () {
alert("hi");
dogTrainer = makeTrainer('dog');
catTrainer = makeTrainer('cat');
});

var makeTrainer = function (type) {
var jumpDogCounter = 0;
var jumpCatCounter = 0;
function trainToJump(val) {
if (val == "dog")
jumpDogCounter += 1;
else
jumpCatCounter += 1;
}
var rollDogCounter = 0;
var rollCatCounter = 0;
function trainToRoll(val) {
if (val == "dog")
rollDogCounter += 1;
else
rollCatCounter += 1;
}

return {
JUMP: function () {
trainToJump(type);
},
ROLL: function () {
trainToRoll(type);
},
TotalJumpTrained: function () {
if (type == 'dog')
return jumpDogCounter;
else
return
jumpCatCounter;

},
TotalRollTrained: function () {
if (type == 'dog')
return rollDogCounter;
else
return
rollCatCounter;
}
}

};

function dogTrain(val) {
if (val == "JUMP")
dogTrainer.JUMP();
else
dogTrainer.ROLL();
}

function catTrain(val) {
if (val == "JUMP")
catTrainer.JUMP();
else
catTrainer.ROLL();
}

function totalDogsTrained() {
var dogsJumpTrained = dogTrainer.TotalJumpTrained();
var dogsRollTrained = dogTrainer.TotalRollTrained();
alert('dogs jump trained:' + dogsJumpTrained + ', dogs roll trained:' + dogsRollTrained);
}

function totalCatsTrained() {
var catsJumpTrained = catTrainer.TotalJumpTrained();
var catsRollTrained = catTrainer.TotalRollTrained();
alert('cats jump trained:' + catsJumpTrained + ', cats roll trained:' + catsRollTrained);
}
</script>

 


And the html is:

<body>
<
input value="Train Dog to Jump" type="button" onclick="dogTrain('JUMP')" />
<
input value="Train Cat to Jump" type="button" onclick="catTrain('JUMP')" />
<
input value="Train Dog to Roll" type="button" onclick="dogTrain('ROLL')" />
<
input value="Train Cat to Roll" type="button" onclick="catTrain('ROLL')" />
<
input value="Total Dogs Trained" type="button" onclick="totalDogsTrained()" />
<
input value="Total Cats Trained" type="button" onclick="totalCatsTrained()" />
</
body>

Code, Code and Code!