A Primer On the JavaScript Object Model

Abhishek S
4 min readMar 25, 2021

Recently, I began my foray into JavaScript. Along my journey, one of the many things which stumped me was the object model. As a Java developer, I found that the object model offered was fundamentally different from what I had been using until then.

This post contains a compilation of everything I have learnt about this. I have written this with the hope that it will be useful to others beginning their journey into JavaScript.

Classes in Class-Based Languages

What is the first thing that pops to your mind when you hear someone say ‘class’ in a programming context? Is it a template describing the contents an object can have? Do you imagine a block of code prefixed with the keyword ‘class’, containing several variables and functions? If you do, you are not entirely wrong, for this is exactly what a class is.

A class is a template, a blueprint containing a set of rules defining state and behaviour. When we create a class, we define the structure an object of our class will have. Every class has variables describing the properties of an object(‘the objects’ state’) and some functions(‘methods’) that modify those properties. Also present is a special ‘constructor’ function that is responsible for initializing objects when they are first created.

This is the definition followed by object-oriented languages like Java and C++. The language of the web browser, however, has a different notion of objects and classes, and in this post, we shall dive into its intricacies.

JavaScript: No Classes. Only Constructor Functions

The Object-Model of JavaScript is vastly different. JavaScript does not natively have classes. All it has are functions. Functions that take parameters, perform tasks and return some output. However, there exist special ‘constructor functions’ that are used to create objects. In JavaScript, these ‘constructor functions’ serve as class definitions. Let us examine this claim by creating a class representing complex numbers.

Create a blank HTML file and type in the following code inside the ‘script’ tag:

function Complex(x,y)
{
this.x=x;
this.y=y;
}
const c1=new Complex(1,2);
console.log(c1);

Above, the function ‘Complex’ is our constructor function. It acts just like the Java or C++ constructor we are so familiar with. We recognize the constructor function because of the ‘this’ keyword in its body. The constructor function takes two parameters, x and y, corresponding to the real and imaginary portions of complex numbers respectively. ‘this’ refers to the current object being created, exactly like its counterparts in Java or C++. ‘Complex’ is thus a parameterized constructor.

We create a new Complex object using the ‘new’ keyword(Java-based syntax). When we log our complex object to the console, we see its two attributes ‘x’ and ‘y’, along with their values.

Adding Methods: The Wrong Way

So far so good. But what if we want to add methods to our constructor function? Let us add a method to return the conjugate of a complex number.

In Java and C++, non-static class methods are bound to objects. That is why we can access them via the object with the dot operator(‘.’). If we extend this analogy further, we would naturally expect the methods of our constructor function to take the form of attributes, i.e., something like this:

function Complex(x,y)
{
this.x=x;
this.y=y;
this.conjugate=()=>
{
return new Complex(this.x,-this.y);
}
}

Here, we create an attribute ‘conjugate’ and assign a function to it. As JavaScript functions are themselves objects, this is valid. We can call our conjugate function like ‘c1.conjugate()’. Note that we use an arrow function for ‘conjugate’. This is because we want ‘this’ to refer to the same object both inside and outside the body of the function. Further information can be found here.

The Right Way: Using the Prototype

But there is a catch. While the above is valid JavaScript, it is not the right way. If we use this technique, we may have problems later, especially with inheritance among classes. The right way to do this is using prototypes.

The prototype is a special object in JavaScript. Every constructor function has its own prototype. The purpose of the prototype is to contain all the member functions of its constructor function and make them available for objects.

Let us rewrite the above snippet the right way using the prototype:

function Complex(x,y)
{
this.x=x;
this.y=y;
};
Complex.prototype.conjugate=function()
{
return new Complex(this.x,-this.y);
};

Here, the conjugate function has been moved inside the prototype of the Complex constructor function(referenced by ‘Complex.prototype’).
As it is inside the prototype, we can safely use a regular function for ‘conjugate’. Execute this function like so:

console.log(c1.conjugate());

Finishing Notes: This is Not the End

Since the prototype in an extremely crucial aspect, let us examine it in further detail. JavaScript provides inheritance via a prototypal mechanism. Every JavaScript object has a prototype from which it inherits all its properties.

Our Complex object c1 inherits its properties, namely its member functions, from the prototype object of its Constructor.

This is just the tip of the iceberg. There is so much that follows after. For further reading, please refer to the following posts and sites:

Happy coding 😊 !

--

--