An overview on an Object Oriented JavaScript

To the reader of this, chances are you’ve probably have some degree of experience with JavaScript. I am supposing you have used some jQuery to enhance a webpage or build complex UI components. Here we will discuss briefly the Object-Oriented nature of JavaScript, mainly object creation patterns as well as inheritance and encapsulation.

JavaScript’s Nature

JavaScript is a dynamic, dynamically typed, interpreted, functional and object-oriented language used largely on the web platform. Its primarily purpose is to manipulate web page elements and make the page content dynamic. Lately, through the power of Google’s V8 JavaScript engine, we can use it as a fully back-end language, writing server-side code, with the help of platforms such as Node JS.

JavaScript is dynamic.

Once the objects have been created their properties (or fields) can be freely removed and new ones can be added. Moreover, in JavaScript, we can directly initiate objects without any class defined.  This topic will be largely covered in the paragraphs below.

JavaScript is dynamically typed.

Variables and object properties can hold values of any type. A variable can hold a string at initiation and later we can change its value to an object.

JavaScript is functional and object-oriented.

JavaScript supports two programming language paradigms: functional programming (first-class functions, closures, reduce for arrays, etc.) and object-oriented programming (mutable state, objects, inheritance, etc.). Functional programming paradigm is essentially a combination of functions. A function is not able to change the outside world, thus allowing to keep strong control over the program flow. The code below will return 10 to the console.

//functional paradigm</code>

var add = function(a, b){

return a + b;

}

var sum = add(4, 6);

console.log("Functional way: " + sum);

Meanwhile, the object-oriented programming paradigm, functions live inside objects as their methods, modifying and manipulating their state. The code below will return -1 to the console. Particularly, this paradigm and the object-oriented JavaScript will be covered throughout this blog.

//object oriented paradigm

var Calc = {

a: 0,

b: 0,

sum: function(a, b){

this.a = a;

this.b = b;

return this.a + this.b;

}

}

var sum = Calc.sum(3, -4);

console.log("OO way: " +sum);

 

Object Oriented JavaScript

As we stated previously, JavaScript is a dynamic robust language. Generally, there are different ways (patterns) of creating JavaScript objects. Below we will focus on three general patterns.

The Literal Way

//assing object {} to variable animal

var animal = {

//object properties

type: "Cat",

voice: "Meow",

speak: function(){

console.log(this.type + " says "+ this.voice);

},

change: function(type, voice){

this.type = type;

this.voice = voice;

this.speak();

}

}

Above we created an object with the curly braces syntax {}, and assigned it to a variable called animal. The object contains multiple members, described with a name: value pattern. So, the first member/property of the animal object is ‘type’ and has the value of “Cat”. The object also contains two methods in its body ‘speak’ and ‘change’. The keyword ‘this’ typically refers to the object in any programming language.

So, calling this.speak() executes the speak method inside the animal object. Notice as how the properties are separated by commas from each-other. The object has been created and defined at the same time. This way of creating an object is called the literal pattern. It’s a straight forward simple approach. It is suitable for creating a singleton pattern, because this way we always have a single object throughout the program.

animal.speak(); //Cat says Meow

animal.change("Dog", "Hum !"); //Dog says Hum !

animal.type = "Cow";

animal['voice'] = 'Muu !';

animal.speak(); //Cow says Muu !

 

animal.name = "Molly";

animal.special = function (){

console.log(this.name + " is a special " + this.type);

}

animal.special(); //Molly is a special Cow

So, continuing with our example; animal.speak() should print ‘cat says meow’. After that, we call the change method, which changes the type and voice members accordingly. Another attribute of the literal pattern is that all the members are public and accessible. This way we change the type and voice to ‘cow’ and ‘muu’ directly. (Notice: there are two ways of doing that in JavaScript, which makes the language even more ambiguous. The first is the dot notation, animal.type,  and the other is bracket notation, animal[‘voice’] ).

Since JavaScript is a dynamic language, we can create object properties in any time. Above, we create a ‘name’ property for our animal object and give it here a value of ‘Molly’, as well as a method called ‘special’, which should print ‘Molly is a special cow’.

Constructor function

What if we want to create multiple instances/objects of the same class/definition? The actual, generally browser supported versions of JavaScript do not feature a class keyword, so there is no way of defining a class in JavaScript (apart from newer versions ES6). However, the way we can achieve this is by using a function as our class.

function Animal(type, voice){

this.type = type;

this.voice = voice;

 

this.speak = function(){

console.log(this.type + " says "+ this.voice);

};

 

this.change = function(type, voice){

this.type = type;

this.voice = voice;

this.speak();

}

}

var animal = new Animal('bird', 'tweet');

animal.speak();

Here, we replicated the code we used in the literal pattern and made it so we can initiate as many ‘Animal’ objects as we want by calling the constructor function with the new keyword. As an Object-Oriented language, JavaScript supports features such as: Inheritance and Encapsulation.

Inheritance, The Prototype Pattern

In classical inheritance, we write a class, which defines an object. Multiple objects can be instantiated from the same class, so you have code in one place which describes several objects in your program. Classes can then be organized into a hierarchy, furthering code reuse. More general code is stored in a higher-level class, from which lower level classes inherit. This means that an object is sharing code with other objects of the same class, as well as with its parent classes.

In the prototypal inheritance form, objects inherit directly from other objects. In JavaScript, every object has a secret link to the object which created it, forming a chain. When an object is asked for a property that it does not have, its parent object will be asked continually up the chain until the property is found or until the root object is reached.

Each function in JavaScript (which are objects themselves) actually has a member called “prototype“, which is responsible for providing values when an object is asked for them. Having this member allows the constructor mechanism (by which objects are constructed from functions) to work. Adding a property to the prototype of a function object will make it available to the constructed object, as well as to all of the objects which inherit from it.

Let’s take the above example and explain it further.

function Animal(type, voice){

this.type = type;

this.voice = voice;

}

 

Animal.prototype.speak = function(){

console.log(this.type + " says "+ this.voice);

}

 

Animal.prototype.change = function(type, voice){

this.type = type;

this.voice = voice;

this.speak();

}

 

console.log(Animal.constructor); //[Function: Function]

console.log(Animal.prototype); //Animal { speak: [Function], change: [Function] }

 

We defined again our Animal function, but this time we are using a different approach on writing its methods. As we mentioned the Animal function has an empty prototype property. There we added two methods, which we want to be accessible in the inherited objects later on.

 

function inheritPrototype(childObject, parentObject) {

var copyOfParent = Object.create(parentObject.prototype);

copyOfParent.constructor = childObject;

childObject.prototype = copyOfParent;

}

The above function that has two arguments, a child and a parent object, will be used to load the parent prototype to the child prototype, so that the latter has all the inherited methods from the parent. (The child prototype will point to a parent object).

 

function Bird(){

Animal.call(this, 'bird', 'tweet'); //runs the Animal function in Bird contexts

this.fly = function(){

console.log("The Bird is Flying");

}

}

inheritPrototype(Bird, Animal);

 

var bird = new Bird();

bird.speak(); //bird says tweet

bird.fly(); //The Bird is Flying

Here we created a Bird function that extends an Animal object. The former runs Animal and has an added fly method. We call the inheritPrototype function explained above and then create a bird object. Calling bird.speak() makes the JavaScript interpreter first scan for a speak method in the bird object, fails to find it and then searches its prototype, were it finally finds and logs to console ‘bird says tweet’.  That is a quick introduction to JavaScript Prototyping, giving you a quick first glance at Inheritance.

Encapsulation, The self-invoking anonymous function expression

The above ‘Animal’ object examples are great, but what if we want scoping and private methods. There is a way around this.

var Animal = (function(){

//private

var _type = 'wolf';

var _voice = 'Auu';

 

function speak(){

console.log(_type + " says " + _voice);

}

 

//return object to the program

return {

speak: speak

}

})()

Animal.speak(); //wolf says Auu

Here we created an Animal variable and assigned it a self-invoking anonymous function, which executes by itself and returns an object as we want. This approach has various benefits, and is widely used in libraries and modular JavaScript world. Firstly, this is a ‘singleton’ pattern giving us only one animal object. Secondly, this way of writing our objects hides its contents from the world/the global scope, our function properties live inside the (bracket) notation making them intentionally private. This way, we are sure that no programmer using our library can directly access methods and properties, except the ones we are returning. So, calling Animal._type will return undefined, however calling Animal.speak() prints ‘wolf says Auu’. This is an interesting approach to achieve modularity and encapsulation in JavaScript.

To conclude and summarize, we talked about the nature of JavaScript as a dynamic robust language. Later we continued by describing three ways of object creation: The literal way, the constructor function and the module pattern (with the use of self-invoking anonymous function), focusing on features such as inheritance and encapsulation. I wish you find this article helpful or interesting somehow, the world of JavaScript is vast, wide-spread and very beautiful. Hopefully, it encourages many other articles covering different aspects of the language, interesting and helpful to our everyday work.

 

References

Introducing JavaScript objects https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects

The Basics of Object-Oriented JavaScript (Leigh Kaszick 2009) https://code.tutsplus.com/tutorials/the-basics-of-object-oriented-javascript–net-7670

OOP In JavaScript: What You NEED to Know http://javascriptissexy.com/oop-in-javascript-what-you-need-to-know/

Leave a Reply

Your email address will not be published. Required fields are marked *