A Guide to Object-Oriented Programming in JavaScript

Objects, classes, encapsulation, polymorphism, and more!

Esakkimuthu E
Oct 27 · 9 min read

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

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

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()

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

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

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

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

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

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

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

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

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

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

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"

Better Programming

Advice for programmers.

Esakkimuthu E

Written by

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

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade