Object Oriented Javascript Tutorial
While typically programming is a set of rules based on certain actions and logic, with time, programmers realized that everyday problems might need a somehow different approach in order to be solved efficiently.
That is where Object Oriented Programming comes to play. But what is OOP?
Let’s discuss it below!
What is Object Oriented Programming?
OOP is a programming paradigm that uses other already established paradigms such as modularity, polymorphism and encapsulation to ensure that we have a certain level of abstraction in order to give our models the shape of real life problems and objects, which is to have their own properties and methods of operation.
Rather than being strictly a list of commands or functions, OOP considers applications to be a set of object collaborating and communicating with each other, while being independent species on their own. Objects can be considered as small machines that contain all the necessary commands to fulfill their responsibilities, be it receiving or sending data to other objects or processing said data.
Generally, programmers trust languages such as Java, C#, Python or PHP etc. more than JavaScript when speaking of Object Oriented Programming because of their distinct class style. However, JavaScript not only supports OOP, but does it wonderfully, since it supports not only inheritance through prototyping but also properties and methods.
Writing your large-scale software using OOP will simplify your code and give you better flexibility and maintenance opportunities, as your code is encapsulated in modules. This also makes your code easier to understand later on, analyse it’s features and present real-life problems.
Creating Objects
We had all this talk about objects, but how to create them? There are multiple ways.
By using new object()
The most simple and basic way of creating an object in JavaScript is by using the operator new object()
. You can use it as shown in the code below:
person = new Object() person.name = "John Doe" person.age = "25" person.run = function() { this.state = "running" this.speed = "10km/h" }
First we create an object named person
by using the operator new Object()
, we have also given this object two properties which are name
and age
and additionally created a function regarding it (method) that tells us the person’s state and speed when invoked.
By using literal notation
Another simple and efficient way of creating objects is by using literal notation. You can do so by using the code snippet below:
person = { name : "John Doe", age : "25", run : function(){alert("Person is called" + this.name)} };
Literal notation can contain arrays or arbitrary Javascript expressions or values (like the one we have used to create the function run()
). However, neither this or the previous way of creating objects are recommended because while it is simple and logical, the code is not reusable, and that would make the whole point of creating object for OOP moot. We have to find another way that would make it possible for us to easily initialize different versions of the created object. That takes us to another aspect of Object Oriented Programming: Prototyping.
Prototype-based Programming
This programming model consists of having an object created using the object constructor function and then reusing it multiple times without having to redefine it each time.
Object Constructors
But what is the object constructor function? It is a very simple Javascript function, so it’s just as robust as any other one. The code would go like below:
function person(name) { this.name = name; this.talk = function() { alert( this.name + " says hello!" ) } } person1 = new person("Felix") person1.talk() person2 = new person("Jessie") person2.talk()
Firstly, we have created an object type that provides us with the flexibility to change and manipulate it’s data easily, and also reuse the code on the way. We have done that using the object constructor, which in our case in person()
, which as promised, is just a simple Javascript function. The properties and methods are declared inside of it by using the keyword this
.
Going from here, since we have already defined the new type, we can use it to initialize different instances of the same object with different values for each property.
Adding methods to the object
Previously we saw that we can very easily add a method to an object by declaring it inside the object constructor. Another very elegant approach is to add it through prototyping. Prototyping is a type of inheritance in Javascript which makes it possible for us to add a method to an object even after it has been defined. That means that we can attach a method to the object long after defining it, without messing up our code.
Let’s add another method to our person
. The code would look like below:
person.prototype.changeName = function(name) { this.name = name; } firstPerson = new person("John") firstPerson.changeName("Bill") firstPerson.talk()
Firstly we have attached the method changeName()
to the object person
by using prototype, and then, after creating a firstPerson
named John, we have renamed it to Bill. All of person
instances will inherit the new method added to it.
Prototyping built-in objects
Prototyping works on both custom and prebuilt Javascript objects, provided the later are initialized using the new
keyword. That means that you can add your own methods to instances such as Date()
, Arrays or Strings.
Since IE5 doesn’t support the methods shift()
and unshift()
methods of an array, our job will be to prototype them in. Take a look at the code snippet below:
if(!Array.prototype.shift) { Array.prototype.shift = function(){ firstElement = this[0]; this.reverse(); this.length = Math.max(this.length-1,0); this.reverse(); return firstElement; } } if(!Array.prototype.unshift) { Array.prototype.unshift = function(){ this.reverse(); for(var i=arguments.length-1;i>=0;i--){ this[this.length]=arguments[i] } this.reverse(); return this.length } }
This way, we have firstly prototyped the shift()
method into our array, and secondly unshift()
, of course, while making sure that they aren’t already built-in the language.
Javascript as an Object Oriented Programming Language
We explained the most basic principles of Object Oriented Programming through Javascript, but let’s get more into the depths of Javascript as OOP. We are going to do this by explaining the most representative concepts such as abstraction, polymorphism, encapsulation etc.
Namespaces
One of the most important implementations of the philosophy of Object Oriented Programming is namespacing. Namespaces are packages of code that contain objects, properties or methods, which in itself is just another object. How can you use them? You can see here how to do that in detail, but we will still explain the most important points.
We can create a namespace using the code below:
var MYAPP = MYAPP || {};
This is a very efficient way of creating a namespace, as it also makes sure there are no collisions of name between what you are trying to create and other instances that may have been used before in your code.
From now on, you can do everything by yourself. All the code goes inside the brackets of your namespace, and you can assign it properties or methods as much as you want. You can even nest them, create sub-namespaces, use aliases etc. Anything that makes it easier and more comfortable for you to code and fully understand what you’re doing goes.
Built-in objects
When designed, Javascript came with some objects prebuilt in it. These objects, in turn, came with a series of properties and methods that make your life (and mine too) so much easier. Some of them are Array, Object, String or Math.
Let’s take Array as an example to explain what we mean by this. An array is an object that contains multiple values in a single variable. It has three properties and a series of methods.
It’s properties are: 1. constructor, 2. length and 3. prototype.
- Constructor is the property that returns the function that created the Array object’s prototype.
- Length sets or returns the number of objects in an array.
- Prototype allows you to add properties and methods to the Array object, as we theoretically mentioned before.
The methods of this object are quite a bit more than the properties, however, they are easy to remember because the do actions that you will have to do often with your arrays. Some of the most honorable mentions are:
- concat() – it joins two arrays and returns the copy of the joined array.
- join() – not to be confused with the method above, this one attaches the elements of an array to the end of a string and then returns it.
- push() – attaches new elements to the end of an array and returns the final length f it.
- pop() – removes the last element of an array and returns it.
These are the most used methods, but the creators of Javascript have gifted you with another very useful batch of methods for this object.
Classes
While you may be used to the concept of classes as used in Java or C++, in Javascript this concept doesn’t exist, as it’s a prototype-based language. However, This language uses functions as constructors for classes. That means that you only have to define a function in case you want to define a class. The code would go like below:
var myclass = function () {};
Now, to make it even more clear what an object is, you can create an object by using the class you just defined, like below:
var class1 = new myclass();
Simple as that.
Constructors
Constructors are functions that are invoked when an object is instantiated. In itself they are just methods of a class, and it does not need to be explicitly defined, since in Javascript, by default, a function is also considered a constructor of an object.
The constructor is used to set the properties and methods of an object, and later you can add more using prototyping.
Take a look at the example below:
var Person = function () { alert('instance created'); }; var person1 = new Person();
In this example we have used a constructor to create an instance of a Person
object, naming it person1
.
Properties
Another object attribute are properties, which are variables contained in the class and set in it’s constructor so that they can be created every time a new instance of the object is created.
To access or work with properties within the class you have to use the keyword this
, while for properties outside of it, just like in languages such as Java or C++, you have to use the dot operator as in the syntax below:
InstanceName.Property
Let’s take a look at a more concrete example as shown in the code snippet below:
var Person = function (firstName) { this.firstName = firstName; alert('Person instantiated'); }; var person1 = new Person('Jane'); console.log('person1 is ' + person1.firstName);
In this piece of code we have defined a constructor for a Person
object, which contains firstName
as a property. We have then accessed this property using the syntax with the dot operator since we access the property outside of a class. However, inside the constructor we have accessed it using the keyword this
.
Methods
Methods in itself are just functions, and are also defined as such, but except for that they follow the same logic as properties. They are called similarly to properties, the only difference being in that methods also take () at the end of their name, and probably even arguments, if needed.
Let’s take a look at the code snippet below:
var Person = function (firstName) { this.firstName = firstName; }; Person.prototype.sayHello = function() { console.log("Hello" + this.firstName); }; var person1 = new Person("Jane"); person1.sayHello();
We have defined a Person
object using the constructor for it, and then have added the method sayHello()
to it by using the prototype. Lastly we have invoked the method by using it according to the syntax that uses the dot operator.
You can invoke methods out of the context, since they are just functions bound to the object as properties. But let’s illustrate our point with the example below:
var Person = function (firstName) { this.firstName = firstName; }; Person.prototype.sayHello = function() { console.log("Hello, I'm " + this.firstName); }; var person1 = new Person("Alice"); var person2 = new Person("Bob"); var helloFunction = person1.sayHello; person1.sayHello(); person2.sayHello(); helloFunction(); console.log(helloFunction === person1.sayHello); console.log(helloFunction === Person.prototype.sayHello); helloFunction.call(person1);
We have firstly created an object and then prototyped the method sayHello()
to it. Then, we have instantiated two objects, and a new variable named helloFunction
. If we access the method sayHello
as usual with the dot operator we would have “Hello, I’m Alice” or “Hello, I’m Bob” as a result. However, if we invoke helloFunction
we would either get an error if we’re on strict mode, or “Hello, I’m undefined” if we’re not on strict mode.
However, we check that helloFunction
is the same as both person1.sayHello
and Person.prototype.sayHello
, so the results would have to be the same, following that logic. The problem is in the keyword this
. When the method is called through the dot operator, this keyword is set to the object we got the method from. However, in the case of helloFunction
it is set as a global variable, which would give us the error. To solve this we call the function as in the last line of the code snippet above, and we would get the correct result.
Inheritance
Inheritance is what comes into play when we want to create a class as a specialized version of another one. We call the derivative a child and the class we got it from, naturally gets the name parent.
The procedure goes like this: We first create another instance of the parent class and then apply the desired modifications to it. Take a look at the example below:
var Person = function(firstName) { this.firstName = firstName; }; Person.prototype.sayHello = function(){ console.log("Hello, I'm " + this.firstName); }; function Student(firstName, subject) { Person.call(this, firstName); this.subject = subject; }
First of all, we have defined a constructor for our object, which is Person
, and then we have added it the method sayHello()
using prototype. Then we define the constructor for Student
, which is done by firstly calling the constructor of the parent and then adding it the property we want.
Encapsulation
Javascript makes it possible for your code to be private, or protected. That means that even though an instance of an object might have inherited a property or a method, you don’t have access to how the method you inherited is constructed. This is called encapsulation.
There’s no doubt that encapsulation makes your code safer, but it is not a requirement or your code to be Object Oriented, even though it’s a perk that comes with prototype-based inheritance.
Polymorphism
What is Polymorphism?
Polymorphism looks like such a difficult thing when you first hear the name, so it might scare you of for a bit. In fact, it has a very clear and concise meaning, which also makes it pretty easy. Basically it is the ability to create an object, function or variable that has more than one form.
It’s primary usage is it’s ability to make objects of different types respond to the same methods, fields or property calls, even though the behavior of the latter would be type-specific. This behavior would be decided at run time, which does not require the programmer to know the type of the object beforehand.
This feature is called dynamic binding (or late binding) and is one of the most flashy and cool features of Polymorphism. However, one of the requirements is that any subclass, superclass or interface should have the same properties with the same sets of values and property names.
Polymorphism in action
While Javascript does not provide user interfaces, it does have subclasses and superclasses. Also, we mentioned all there is to know about it’s prototype-based inheritance.
Let’s take a similar example. We will create an object named Person
and will use it to create another class named Manager
through inheritance. Both classes will contain the same method, which in our case will be wake_up()
. After doing this, we will instantiate a series of objects from these classes and put them in an array. We will loop through each one and see how dynamic binding will work with them.
Let’s get to work. First, we define the Person
class as shown in the code snippet below:
Person = function (id, name, age) { this.id = id; this.name = name; this.age = age; } Person.prototype = { wake_up: function () { alert('A person is awake'); }, get_age: function () { return this.age; } }
As you see, this object has three properties, which are id
, age
and name
, and after that we have prototyped in two methods which are wake_up
and get_age
.
After doing that, let’s create an Inheritance class so that our other classes can inherit from Person
. See the code below:
Inheritance_Manager = {}; Inheritance_Manager.extend = function (subClass, baseClass) { function inheritance() { } inheritance.prototype = baseClass.prototype; subClass.prototype = new inheritance(); subClass.prototype.constructor = subClass; subClass.baseConstructor = baseClass; subClass.superClass = baseClass.prototype; }
Now we define the Manager class
as below:
Manager = function (id, name, age, salary) { Manager.baseConstructor.call(this, id, name, age); this.salary = salary; }
Since we now defined the class Manager
, what’s left now is for it to inherit from our original class. That would be done by using the code snippet:
Inheritance_Manager.extend(Manager, Person);
Now that both classes are fully defined, it is time to create some objects and store them into an array. We would use the code below:
var arrPeople = new Array(); arrPeople[0] = new Person(1, 'Joe Tester', 26); arrPeople[1] = new Manager(1, 'Joe Tester', 26, '20.000');
What is left now is only to see how our method will behave with object that are different from each other. Take a look at the snippet below:
for (var i in arrPeople) { arrPeople[i].wake_up(); alert(arrPeople[i].get_age()); }
This is what we call polymorphism. When we have objects that have the same interface but different implementations it makes things very easy, which is why Javascript should be more recognized for it’s fully polymorphic form.
Download the source code
This was an example of Object Oriented Javascript. Download the source code for this tutorial:
You can download the full source code of this example here : ObjectOrientedJavascript