Chapter 14 - Object Oriented JavaScript

Object Oriented JavaScript

Object oriented programming or OOP is a methodology to create our program using Objects and Classes. The basic idea of OOP is that we use objects to model real world things that we want to represent inside our programs, and provide a simple way to access functionality that would otherwise be hard or impossible.

Objects can contain property, which represents information about the thing we are trying to model and methods or actions that represents a behavior. For example, if we think a car as an object, then the number of wheels, the type of car, the color of car becomes the properties of the car. And starting or stopping the car becomes actions. Data in objects can be stored neatly without exposing to the outer world (which is called encapsulation), can be given a specific name to refer to (which is sometimes called a namespace).

Consider we are going to develop an application for an organization where there are developers and managers. To handle the data of developers and managers we could create an object model like below:

 1 function Developer(name, id) {
 2     this.name = name;
 3     this.id = id;
 4     this.role = 'Developer';
 5     this.greeting = function() {
 6         console.log('Hello, I am a Developer');
 7     }
 8 }
 9 function Manager(name, id) {
10     this.name = name;
11     this.id = id;
12     this.role = 'Manager';
13     this.greeting = function() {
14         console.log('Hello, I am a Manager');
15     }
16 }

If you can observe the above code, it has duplicate properties in both model, name and id. We can make this better by creating one parent objects and create two sub-objects for developer and manager.

 1 function Employee(name, id) {
 2     this.name = name;
 3     this.id = id;
 4 }
 5 function Developer(name, id) {
 6     Employee.call(this, name, id);
 7     this.role = 'Developer';
 8     this.greeting = function() {
 9         console.log('Hello, I am a Developer');
10     }
11 }
12 function Manager(name, id) {
13     Employee.call(this, name, id);
14     this.role = 'Manager';
15     this.greeting = function() {
16         console.log('Hello, I am a Manager');
17     }
18 }

We have moved the common properties to the top of the prototype chain and let the child objects to call them. This make our developer and manager constructors more manageable. If you inspect more, we can see that the greeting action has almost similar in both. It is same in both except for the role. So we can also move this method to the top.

 1 function Employee(name, id) {
 2     this.name = name;
 3     this.id = id;
 4 }
 5 Employee.prototype.greeting = function() {
 6     console.log('Hello, I am a ' + this.role);
 7 }
 8 function Developer(name, id) {
 9     Employee.call(this, name, id);
10     this.role = 'Developer';
11 }
12 Developer.prototype = Object.create(Employee.prototype);
13 Developer.constructor = Developer;
14 function Manager(name, id) {
15     Employee.call(this, name, id);
16     this.role = 'Manager';
17 }
18 Manager.prototype = Object.create(Employee.prototype);
19 Manager.constructor = Manager;

This looks even better. We have, like moved the common properties to top, moved the common methods to the top. We have also make our Developer and Manager inherits data and behavior from the Employee, so we can reuse functionality common to all the object types rather than having to duplicate it. Now let us check our models by creating instances of them.

1 var christine = new Manager('Christine', 1);
2 var joseph = new Developer('Joseph', 2);
3 christine.greeting();
4 // Hello, I am a Manager
5 joseph.greeting();
6 // Hello, I am a Developer

The greeting method is same in both objects and implemented the same functionality. But their result are different based on child objects. The ability of multiple object types to implement the same functionality is called polymorphism.

If you have noticed, we have assigned the constructor property of Developer (or Manager) to the same function again after the prototype. This is because, when we are overwriting the prototype, it also overwrites the constructor property to Employee. So we have manually adjust it back to its original value.

One of the other features in OOP is Encapsulation. Encapsulation is the ability of an object to be a container (or capsule) for its member properties, including variables and methods. This object can protect its data from outside world or restricting its access. Imaging our Developer object needs to have a private data which is noOfWorkingDays. It should be accessed like name or id which are common. Let us see how can we achieve this.

If you can remember, functions create scope. That means variables declared inside a function can not be accessed from outside. So creating a local variable, we can encapsulate our data inside the function.

1 function Developer(name, id) {
2     Employee.call(this, name, id);
3     this.role = 'Developer';
4     var numOfWorkingDays = 0;
5 }
6 var joseph = new Developer('Joseph', 2);
7 joseph.noOfWorkingDays; // undefined

If we want to expose this data to outside, we can create methods to write and read the data from the object. This way we can be sure that there is no way to directly manipulate our private data noOfWorkingDays. Any read or write operation should be done from our generated methods.

 1 function Developer(name, id) {
 2     Employee.call(this, name, id);
 3     this.role = 'Developer';
 4     
 5     var numOfWorkingDays = 0;
 6     
 7     this.updateWorkingDays = function() {
 8         numOfWorkingDays++;
 9     }
10     
11     this.getWorkingDays = function() {
12         return numOfWorkingDays;
13 }

We have created a method updateWorkingDays to increment the working days by 1 whenever invoked and getWorkingDays to access the value of the private variable numOfWorkingDays. Note that these methods are specific to Developer. Manager does not have these methods.

1 var joseph = new Developer('Joseph', 2);
2 joseph.getWorkingDays(); // 0
3 joseph.updateWorkingDays();
4 joseph.getWorkingDays(); // 1

These private variables private to these objects which means other instance of the Developer object will have its own numOfWorkingDays.

1 joseph.getWorkingDays(); // 1
2 var andrew = new Developer('Andrew', 3);
3 andrew.getWorkingDays(); // 0
4 andrew.updateWorkingDays();
5 andrew.getWorkingDays(); // 1

Because of the way JavaScript works, with the prototype chain, etc., the sharing of functionality between objects is often called delegation. Specialized objects delegate functionality to a generic object type.

In terms of using inheritance in your own code, you probably won’t use it often, especially to begin with, and in small projects. It is a waste of time to use objects and inheritance just for the sake of it when you don’t need them. But as your code bases get larger, you are more likely to find a need for it. If you find yourself starting to create a number of objects that have similar features, then creating a generic object type to contain all the shared functionality and inheriting those features in more specialized object types can be convenient and useful.

When using inheritance, you are advised to not have too many levels of inheritance, and to keep careful track of where you define your methods and properties. It is possible to start writing code that temporarily modifies the prototypes of built-in browser objects, but you should not do this unless you have a really good reason. Too much inheritance can lead to endless confusion, and endless pain when you try to debug such code.

Finally, using functions with prototype looks like lot of work to link objects. But since ES6 introduction of class, extends and super, it becomes very easy to create classes and share functionalities among them. We will explain all the ES6 features in the coming lessons.

Chapter 14 - Quiz

Oops! That was an incredible achievement. OOP or Object oriented programming is an important concept not only in JavaScript but in most of the languages that every developer should know. Go ahead and take this simple questions before you continue your journey.

1. Object oriented programming or OOP is a methodology to create our program using which of these?

  1. Object and class
  2. Data and behavior
  3. Functions and scope

2. If you think of a car as an object, which of the below can be said to equal to starting the car?

  1. method
  2. property
  3. data

3. Having a parent class to have common properties and methods leads to reducing code duplication.

  1. True
  2. False

4. The ability of multiple object types to implement the same functionality is called what?

  1. Polymorphism
  2. Encapsulation
  3. OOP

5. The idea of OOP is to use objects to model real world things that we want to represent, and provide a simple way to access functionality that would otherwise be hard or impossible.

  1. True
  2. False

6. A class sometimes can shield its member from outside world and restrict access to them. How is this behavior called?

  1. Polymorphism
  2. Encapsulation
  3. OOP

7. Find the missing piece of code to complete the inheritance?

 1 function Employee(name, id) {
 2     this.name = name;
 3     this.id = id;
 4 }
 5 
 6 Employee.prototype.greeting = function() {
 7     console.log('Hello, I am a ' + this.role);
 8 }
 9 
10 function Developer(name, id) {
11     Employee.call(this, name, id);
12     this.role = 'Developer';
13 }
14 
15 // .....
16 Developer.constructor = Developer;
  1. Developer.prototype = Object.create(Employee.prototype);
  2. Employee.prototype = Object.create(Employee.prototype);
  3. Employee.prototype = Object.create(Developer.prototype);

8. How can we create encapsulation in JavaScript?

  1. Using functions scope
  2. Using prototype
  3. Using inheritance

9. Does different instances of a class share the same private variables?

  1. No
  2. Yes

10. It is advised to have too many levels of inheritance. State true of false.

  1. True
  2. False

11. With the prototype chain, etc., the sharing of functionality between objects is called … ?

  1. sharing
  2. delegation
  3. polymorphism

Answers

  1. a); Object oriented programming or OOP is a methodology to create our program using which of Object and class.
  2. a); Starting or stopping car denotes an action. And in objects methods are doing some actions and properties are having some data.
  3. a); True. When a parent class have common properties and methods, it leads to reducing code duplication.
  4. a); The ability of multiple object types to implement the same functionality is called Polymorphism.
  5. a); True. The basic idea of OOP is that we use objects to model real world things that we want to represent inside our programs, and provide a simple way to access functionality that would otherwise be hard or impossible.
  6. b); Encapsulation is the ability of an object to be a container (or capsule) for its member properties, including variables and methods. This object can protect its data from outside world or restricting its access.
  7. a); To inherit properties from Employee object, we need to modify the prototype of Developer to Developer.prototype = Object.create(Employee.prototype).
  8. a); Functions create scope, that means variables declared inside a function cannot be accessed from outside. So creating a local variable, we can encapsulate our data inside the function.
  9. a); The private variables private to these objects which means other instance of the Developer object will have its own numOfWorkingDays.
  10. b); When using inheritance, you are advised to not have too many levels of inheritance since it can lead to endless confusion, and pain.
  11. b); The sharing of functionality between objects is often called delegation. Specialized objects delegate functionality to a generic object type.