A Guide to Object-Oriented Programming in JavaScript

Objects, classes, encapsulation, polymorphism, and more!

Esakkimuthu E
Better Programming
Published in
9 min readOct 27, 2019

It all starts with an object.

An object is a thing that we interact with, it has properties and methods. The object is the heart of object-oriented programming, not only for JavaScript but also for Java, C, C++, and others. Stop thinking about individual variables and functions and start thinking in terms of self-sufficient objects.

Here’s a list of concepts that are most often used when talking about object-oriented programming (OOP):

  • Object, property, and method
  • Class
  • Encapsulation
  • Abstraction
  • Reusability/inheritance
  • Polymorphism
  • Association
  • Aggregation
  • Composition

Object, property, and method

Object literal

Create a new object in JavaScript by setting its properties inside curly braces. Object literals property values can be any data types, like function literals, arrays, strings, numbers, or boolean.

Let’s create an object with a named book, with properties such as author, published year, title, and a method — summary.

const book = {
title: "Hippie",
author: "Paulo Coelho",
year: "2018"
}

After creating an object you can get the value with dot notation. For example, we can get the value of the title with book.title. We can also access the properties with square brackets: book[‘title’].

Object constructor

Object constructor is the same as a regular function. It will be called each time an object is created. We can use them with the new keyword. Object constructor is useful when we want to create multiple objects with the same properties and methods.

const book = {
title: "Hippie",
author: "Paulo Coelho",
year: "2018"
}
const book1 = {
title: "The Alchemist",
author: "Paulo Coelho",
year: "1988",
}

If we want to create multiple book objects we have to duplicate the code for each book. We can keep creating books but it’s kind of a pain — the object constructor helps us to reuse the object literal.

function Book(title, author, year) { 
this.title = title;
this.author = author;
this.year = year;
}
const book1 = new Book ('Hippie', 'Paulo Coelho', '2018');console.log(book1);
> Book {
title: "Hippie",
author: "Paulo Coelho",
year: "2018"
}
// if we want to create more than one book just we call function book with new keyword.const book2 = new Book ('The Alchemist', 'Paulo Coelho', '1988');

book1 and book2 create an instance of Book and assigned it to a variable. To find out whether an object is an instance of another one. We can use instanceof.

book1 instanceof Book
> true

Object.create()

Every object in JavaScript will create from the master Object. whenever we use object with a capital ‘O’ it refers to the master object. We can print the master object in the console. The master object has the number of methods and here we are going to see Object.create() method.

The Object.create() method creates a new object, using an existing object as the prototype. Here’s the basic syntax:

Object.create(proto, [propertiesObject])

proto is the prototype of the newly-created object. propertiesObject is an optional one.

Let’s take a simple example:

const Book = { 
summary : function() {
console.log(`${this.title} is written by ${this.author}.`)
}
}
const book1 = Object.create(Book);
book1.author = "Paulo Coelho";
book1.title = "Hippie";
console.log(book1.summary());
> Hippie is written by Paulo Coelho.

In the above example, we created a prototype object book1 and assigned a value for author and title. We can see the summary function inside the proto object:

We will look at the Object.create() method in detail below.

Class

Class is not an object — it is the blueprint of an object. Classes are special functions. You can define functions using function expressions and declarations and you can define classes that way as well. We can create the number of objects using the blueprint.

You can use the class keyword and the name of the class. The syntax is similar to that of Java.

Class syntax is a nice way to use object-oriented programming and managing prototypes:

let Book = function(name) { 
this.name = name
}
let newBook = function(name) {
Book.call(this, name)
}
newBook.prototype = Object.create(Book.prototype);
const book1 = new newBook("The Alchemist");

This is using ES6 class syntax:

class Book {
constructor(name) {
this.name = name
}
}
class newBook extends Book {
constructor(name) {
super(name);
}
}
const book1 = new newBook("The Alchemist");

Class syntax is syntactical sugar — behind the scenes, it still uses a prototype-based model. Classes are functions, and functions are objects in JavaScript.

class Book {
constructor(title, author){
this.title = title;
this.author = author;
}
summary() {
console.log(`${this.title} written by ${this.author}`);
}
}
const book1 = new Book("", "");console.log(typeof Book);
> "function"
console.log(typeof book1);
> "object"

Encapsulation

Encapsulation means hiding information or data. It refers to the ability of the object to execute its functionality without revealing any execution details to the caller. In other words, the private variable is only visible to the current function and is not accessible to the global scope or other functions.

const Book = function(t, a) {
let title = t;
let author = a;

return {
summary : function() {
console.log(`${title} written by ${author}.`);
}
}
}
const book1 = new Book('Hippie', 'Paulo Coelho');
book1.summary();
> Hippie written by Paulo Coelho.

In the above code the title and the author are only visible inside the scope of the function Book and the method summary is visible to the caller of Book. So the title and the author are encapsulated inside Book.

Abstraction

Abstraction means implementation hiding. It is a way of hiding the implementation details and only showing the essential features to the caller. In other words, it hides irrelevant details and shows only what’s necessary to the outer world. A lack of abstraction will lead to problems of code maintainability.

const Book = function(getTitle, getAuthor) { 
// Private variables / properties
let title = getTitle;
let author = getAuthor;
// Public method
this.giveTitle = function() {
return title;
}

// Private method
const summary = function() {
return `${title} written by ${author}.`
}
// Public method that has access to private method.
this.giveSummary = function() {
return summary()
}
}
const book1 = new Book('Hippie', 'Paulo Coelho');book1.giveTitle();
> "Hippie"
book1.summary();
> Uncaught TypeError: book1.summary is not a function
book1.giveSummary();
> "Hippie written by Paulo Coelho."

Reusability/Inheritance

JavaScript inheritance is a mechanism allows us to create a new class using the existing class. It means the child class inherits all the properties and behaviors of the parent class.

Generally, JavaScript is not a class-based language. The keyword class was introduced in ES6 but is syntactical sugar, JavaScript remains prototype-based. In JavaScript inheritance is achieved by using the prototype. This pattern is called Behavior Delegation Pattern or prototypal inheritance.

Let’s consider our book example:

function Book(title, author, year) { 
this.title = title;
this.author = author;
this.year = year;
this.summary = function() {
console.log(`${this.title} is written by ${this.author}.`)
}
}
const book1 = new Book ('Hippie', 'Paulo Coelho', '2018');
const book2 = new Book ('The Alchemist', 'Paulo Coelho', '1988');

Prototypal inheritance

For each instance of Book, we’re recreating the memory for the methods from the base class. These methods must be shared across all instances — they should not be specific to the instance. Here the prototype comes into the picture:

let Corebook = function(title) {
this.title = title
}
Corebook.prototype.title = function() {
console.log(`name of the book is ${this.title}`);
}
Corebook.prototype.summary = function(author) {
console.log(`${this.title} is written by ${this.author}`);
}
let Book = function(title, author) {
Corebook.call(this, title, author)
}
Book.prototype = Object.create(Corebook.prototype);let book1 = new Book('The Alchemist', 'Paulo Coelho');book1.title();
> name of the book is The Alchemist
book1.summary();
> The Alchemist is written by Paulo Coelho

In the above code, the instance of Book has a copy of the prototype, which is linked to the prototype of Book, which in turn links to the prototype of Corebook.

Polymorphism

The ability to call the same method on different objects and have each of them respond in their own way is called polymorphism.

let book1 = function () {}
book1.prototype.summary = function() {
return "summary of book1"
}
let book2 = function() {}
book2.prototype = Object.create(book1.prototype);
book2.prototype.summary = function() {
return "summary of book2"
}
let book3 = function() {}
book3.prototype = Object.create(book1.prototype);
book3.prototype.summary = function() {
return "summary of book3"
}

var books = [new book1(), new book2(), new book3()];
books.forEach(function(book){
console.log(book.summary());
});
> summary of book1
> summary of book2
> summary of book3

Relationships between the objects will be defined by Association, Aggregation, and Composition.

Association

Association is the relationship between two or more objects. Each Object is independent. In other words, association defines the multiplicity between objects: one-to-one, one-to-many, many-to-one, many-to-many.

function Book(title, author) { 
this.title = title;
this.author = author;
}
const book1 = new Book ('Hippie', 'Paulo Coelho');const book2 = new Book ('The Alchemist', 'Paulo Coelho');book2.multiplicity = book1

book1 was assigned to the property of multiplicity to object book2. It shows the relationship between objects book1 and book2. Both can be added and removed independently.

Aggregation

Aggregation is a special case of an association. In the relationship between two objects, one object can have a more major role than the other. In other words, when an object takes more ownership than another one, that is aggregation. The owner object is often called the aggregate and the owned object is called the component. Aggregation is also called a “Has-a” relationship.

function Book(title, author) { 
this.title = title;
this.author = author;
}
const book1 = new Book ('Hippie', 'Paulo Coelho');const book2 = new Book ('The Alchemist', 'Paulo Coelho');let publication = {
"name": "new publication Inc",
"books": []
}
publication.books.push(book1);
publication.books.push(book2);

book1 and book2 were added to books under publication object. If the publication object is deleted until book1 and book2 are available, then both Book and publication live independently.

Composition

Composition is a special case of aggregation. Composition is when an object contains another object and the contained object can’t live without the container object.

let Book = {
"title": "The Alchemist",
"author": "Paulo Coelho",
"publication": {
"name": "new publication Inc",
"address": "chennai"
}
}

Here the property publication is strictly bounded with the Book object, and publication can’t live without theBook object. If the Book object id was deleted, then the publication would also be deleted.

Composition Over Inheritance

Inheritance is when an object is based on another object. For example, book1 has inherited properties and methods for books like title, author and summary. So it creates the relationship that book1 is-a Book.

The composition is collecting simple objects and combining them to build more complex objects. To build book1 we need methods, like paper and a pen. So it creates a relationship that book1 has-a paper and a pen:

const getTitle = (data) => ({
title : () => console.log(`title : ${data.title}`)
});
const getAuthor = (data) => ({
author : () => console.log(`author: ${data.author}`)
});
const getSummary = () => ({
summary :() => console.log(`book summary need to update.`)
});
const Book = (title, author) => {
const data = {
title,
author
}

return Object.assign({},
getTitle(data),
getAuthor(data),
getSummary()
)
}
let book1 = Book('The Alchemist', 'Paulo Coelho');book1.title();
> "title : The Alchemist"
Esakkimuthu E
Esakkimuthu E

Written by Esakkimuthu E

Front End Developer with over eight years of commercial experience, Passionate about front-end architecture, performance, scalable code, and thoughtful design.

Responses (7)

Write a response