JavaScript Classes

For any one with classical OOPs (Java, C#, etc) background, working in JavaScript might not be easy, as it doesn’t contain keywords such as class , static , private , public or protected , that one might be used to. The way JavaScript works is, you define a class using function which acts as its constructor and then invoke it using the keyword new. Let’s Create a simple Person class.

Have look a the following code


function Person(name, age){
    this.name = name,
    this.age = age

    console.log('Hi! ' + this.name);
}

var john = new Person("John Doe", 21);

If you save it and run it (I’m assuming, you already know that), you must see the following output on the console


Hi! John Doe

Variable Privacy

Now let’s have a look at privacy of variable.


function Person(name, age){
    
    //Public Variable(s)
    this.name = name,
    this.age = age

    //Private Variable(s)
    var max_age = age + Math.floor(Math.random()*(100-age)); 

    console.log('Hi! ' + this.name + '\n');
}

//Static Variable(s)
Person.staticVar = "Lorem Ipsum";

var john = new Person("John Doe", 21);

console.log("==Trying to access public variables==:\n" + john.name + " is " + john.age + "\n");

console.log("==Trying to access private variables==:\nHis expected life span is " + john.max_age + "\n\n");

console.log("==Trying to access static variables==:\nPerson says " + Person.staticVar + "\n" + john.name + " says " + john.staticVar +"\n");

You must see the following on the console


Hi! John Doe

==Trying to access public variables==:
John Doe is 21

==Trying to access private variables==:
His expected life span is undefined


==Trying to access static variables==:
Person says Lorem Ipsum
John Doe says undefined

As you can see, the variables behave as expected.

Methods/Functions Privacy

Now lets have a look at the methods/functions. JavaScript doesn’t have any equivalent of protected methods. Instead it has, what is called a privileged methods.


function Person(name, age){
    
    //Public Variable(s)
    this.name = name,
    this.age = age

    //Private Variable(s)
    var max_age = setMaxAge();

    /** 
    *  Private Method(s)
    *  They have access to only private variable(s) and private method(s)
    **/
    function setMaxAge(){
        return age + Math.floor(Math.random()*(100 - age));        
    } 

    /**
    *  Privileged Method(s)
    *  They have access to both private and public variables and methods
    **/
    this.theFuture = function(){
        console.log(this.name + ' is expected to live for ' + max_age + ' years');
    }
}

//Static Variable(s) and methods(s)
Person.staticVar = "Lorem Ipsum";

/**
*  Static Method(s)
*  They have access to only static variable(s)and methods(s)
**/
Person.staticFunc = function(){
    console.log('Person can say ' + Person.staticVar);
}

/** 
*  Public Method(s)
*  They have access to only public variable(s) and methods(s)
**/
Person.prototype.greet = function(say) {
    console.log( this.name + ' says: ' + say );
};


var john = new Person("John Doe", 21);

john.greet('Hello World!');

john.theFuture();

Person.staticFunc();


The output.


John Doe says: Hello World!
John Doe is expected to live for 59 years
Person can say Lorem Ipsum

(Note: The second line will give different value every time you run it.)

Summary

As you can see, the methods have limited access to variable scope by default.

Type of methodVariable/Method access limitDefined in

Public Public prototype
Private Private constructor
Privileged Public, Private constructor

Limitations and Workarounds

You have seen that we don’t have access to public variables in private methods and vice-versa. One of the ways to resolve the first issue is to assign this to some variable and use it to access public variables inside private methods. Here I will use that as a holder. The updated code looks like below and will produce same result.


function Person(name, age){
    
    //Public Variable(s)
    this.name = name,
    this.age = age

    //for accessing pucblic variables
    that = this;

    //Private Variable(s)
    var max_age = setMaxAge();

    /** 
    *  Private Method(s)
    *  They have access to only private variable(s)
    **/
    function setMaxAge(){
        return that.age + Math.floor(Math.random()*(100 - that.age));        
    } 

    /**
    *  Privileged Method(s)
    *  They have access to both private and public variables
    **/
    this.theFuture = function(){
        console.log(this.name + ' is expected to live for ' + max_age + ' years');
    }
}

//Static Variable(s)
Person.staticVar = "Lorem Ipsum";

/**
*  Static Method(s)
*  They have access to only static variable(s)
**/
Person.staticFunc = function(){
    console.log('Person can say ' + Person.staticVar);
}

/** 
*  Public Method(s)
*  They have access to only public variable(s)
**/
Person.prototype.greet = function(say) {
    console.log( this.name + ' says: ' + say );
};


var john = new Person("John Doe", 21);

john.greet('Hello World!');

john.theFuture();

Person.staticFunc();


John Doe says: Hello World!
John Doe is expected to live for 99 years
Person can say Lorem Ipsum

As with the problem of accessing private variables in public methods, it can be solved by defining privileged getter/setter for the variable.

Add the following code to the constructor


this.setMaxAge = function (age) {
    max_age = age;
}

this.getMaxAge = function(){
    return max_age;
}

and this, below the constructor


Person.prototype.resetMaxAge = function(){
    var newAge = this.age + Math.floor(Math.random()*(100-this.age));
    this.setMaxAge(newAge);
    console.log( this.name + '\'s life expectancy has changed to ' + this.getMaxAge() +' years');
}

now when you call john.resetMaxAge(), you’ll see the following result


John Doe's life expectancy has changed to 90 years

Conclusion

This is the way I use to create JavaScript Classes. This isn’t the only way. There are other ways to create classes like Object.create(), and others which I may cover in future posts.

Leave a Reply