Sunday 25 December 2011

JS OOP

If you thought that JS is written only using functions and objects, well, you are kind of wright :). But actually it is the most permissive (in my opinion) OOP language.
A class in js is defined using "function" and when we use something like:
function sum(a,b){
    return a+b;
}
we actually create a new class named "sum". All that we see inside the "{...}" is actually the constructor, so when we call
var c = sum(1,2)
c will be equal to 3, because that is what the constructor of the class returns, the sum of the variables.
If we would use
var c = new sum(1,2);
c would be an instance of the class sum. Of course for the purpose of simplicity class sum dose not have any variables or methods attached to it, so let's go ahead and make this a little more complex.
Let's define a new class that we can also use as a standalone function.

function Animal(name,species){
    // standard (for me) way to use default values for params
    // also the params will be private vars in our class
    name = name || "Unnamed";
    species = species || "Unknown";

    // setup some public vars
    this.animalTitle = name + ' the ' + species;

    // setup some private vars
    var age = 0;

    // create a private methos
    var grow = function(years){
        return age + years;
    }

    // some public methods(functions :) )
    this.getOlder = function(how_much){
        // here we access the private var
        // and a public one
        how_much = how_much || 0;
        age = grow(how_much);
        this.animalTitle = name + ' the ' + species + ' at ' + age + ' years old';
    }

    // using return to demonstrate how it works as a simple function
    return this.animalTitle;
}
Ok, now let's explain more.
name = name || 'Unnamed' is the same as if(name == null) name = 'Unnamed';. BTW, if you expect name, or whatever the param name will be, to be a bool or number you should use ==null or name = (name == null ? "Unnamed" || name) because 0 or false will make act in the expression used by me the same way as null.
this.animalTitle is a public variable that will be readable/writable, will see later.
age is a private variable that can only be used inside the class (also as I said in the inline comments, the params are also considered private vars).
grow is a private method, a function that can be called only inside the class definition.
And getOlder is a public method that can be called or overwritten.
Here is a example on how this can be used as a function:

var my_pet = Animal("Rex","Dog");
alert(my_pet);
// will alert "Rex the Dog"
or as a class definition to create an object:
var my_pet = new Animal("Simba","Lion");
alert(my_pet);
// will alert [object Object]
// to get a better understanding of what this is we can use GC console ot FF firebug and do:
console.log(my_pet)
alert(my_pet.animalTitle)
// will alert 'Simba the Lion'
my_pet.getOlder(10); // calling a public method
alert(my_pet.animalTitle)
// will alert 'Simba the Lion 10 years old'
my_pet.animalTitle = 'Custom title for my pet'; // overwriting a public member of the object
alert(my_pet.animalTitle)
// will alert 'Custom title for my pet'
Next we should talk about the prototype object.
Most of the js community talks about the prototype object as giving the functionability to add public methods/vars to classes. I actually don't like how this sounds and I will refraze it like this: "The prototype object is used to extend methods and variables of a class with the downside that you won't be able to use the private vars". Ok, now let's get back to some code:

// using our class Animal
Animal.prototype.whatToSay = 'I can say this:';
var my_pet = new Animal();
alert(my_pet.whatToSay);
// will alert 'I can say this:'

// we want to add a method named speak
Animal.prototype.speak = function(){
    // we can use public methods from our constructor and also ones we defined with prototype
    alert(this.whatToSay + ' My name is ' + this.animalTitle);
}
// we can't use age or grow() here because we don't have access to anything
// not defined in the constructor (function) with this. (public stuff)
var my_pet2 = new Animal();
my_pet2.speak();
// will alert 'I can say this: I am Unknown the Unnamed'
// why Unnamed? because we didn't gave him a name when we created him and this is the
// default string we gave it
var my_pet3 = new Animal('Bobo','Bear');
my_pet3.speak();
// will alert 'I can say this: I am Bobo the Bear'
Hope this will help somebody on a better understanding of the OOP in JS. Will continue with object members and inheritance.

No comments:

Post a Comment