Saturday, October 30, 2010

Javascript classes

In this post, i am going to discuss how to create classes in javascript and how classes in javascript behave differently as compared to classes in other languages like Java.

Here are our objectives.

  1. Learn how to create javascript classes.
  2. Learn how to create properties in javascript classes.
  3. Accessing the properties of javascript classes.


Lets walk through them one by one.

In javascript, classes are created by merely creating a constructor function of the class. The functions declared within the constructor on the 'this' object become the "public" functions of the class. The variables declared within the function on the "this" object become the "public" variables of the class.

Lets see with an example of a class called person.

function Person(name){
      this.name = name;
      this.getName=function(){return this.name;};
      
      this.setName=function(nameArg){
       console.log(nameArg);
       this.name=nameArg;
      };
     }

As seen above, i created a function named Person. Then i created a property called name on the "this" object. And i also created a bean style getter and setter for this property on the "this" object. Here is how we instantiate the class.

var p1= new Person("ryan");

As you see, instantiation is pretty simple and quite similar to your conventional languages like Java.

Now lets see how to invoke the methods and access the properties.

console.log(p1.name);
     
console.log(p1.getName());
     
p1.setName("public name");
     
console.log(p1.getName());


Note that the property "name" is a public property, because it is declared on the this variable. So, it can be accessed without any getters and setters. I have simply introduced getters and setters for the "name" property to demonstrate how private properties differ from public properties, which i will be covering in the next example.

So far, so good.

Now lets see how the code for the person class would change if i were to make the "name" property private.

function Person(){
      var name;
      this.getName=function(){return name;};
      this.setName=function(nameArg){       
       name=nameArg;
      };
     }


Okey, lets make a note of the differences. First thing you see is that i created a property called "name" using the var keyword. Now it is a private variable. The point here is that all the variables declared in side a class, that are not declared on the this variable are private variables. And the public getter/setter functions, are allowed to set and get the private variable directly without any using the "this" keyword. This is possible due to javascript closures. Closures allow you to access locally declared variables from with locally declared methods. And the scope of the local variable lasts as long as the scope of functions where it is being used.

As i said before, if all local variables are private variables, then the following class declaration should be equivalent to the previous one for declaring private properties.

function Person(name){
      this.getName=function(){return name;};
      this.setName=function(nameArg){
       console.log(nameArg);
       name=nameArg;
      };
     }

And guess what, they are equivalent. Thats because, the variable passed as an argument in a constructor is a local variable in the function, just as in Java. Hence, it automatically becomes a private variable.

Here's how it can be accessed

console.log(p1.getName());
     
     p1.setName("surprise");
     
     console.log(p1.getName());

Pretty simple.

However, it is better not to have private variables and corresponding getter and setter methods for them because for each object that you create, a new copy of the methods would be created for each object, and hence it would have significant memory overload if you intend to create several objects. Its always better to create public properties and mainly use function pointers instead of functions in your classes. Ill be discussing about these topics in my upcoming posts.

Till then.
Hasta La Vista!

Happy Programming :)
Signing Off
Ryan

No comments: