Skip to main content

Primer: Introduction to Object Orientation and Prototypes in JavaScript

Firesand: End to End Security for your Business

Introduction

This article is one of a collection of primer articles, providing a basic introduction to various topics, for reference in other – more in-depth – articles. These primer articles are written as people come to security pages from various backgrounds, be it a software engineer who wants to understand an issue they need to fix (or prevent one from occurring in the first place) or a penetration tester with no background in software engineering, who wants to understand and know how to exploit a particular issue.

This primer is regarding Object Orientation in JavaScript, and JavaScript Prototypes. Before reading this article, if Object Orientation is not something you are familiar with, it would be worth reading the our primer article on Object Orientation.

 

Object Orientation in JavaScript 

JavaScript has number of methods for defining and building objects, depending on the version of JavaScript you use: (i) Classes, (ii) Constructor Functions, (iii) Object Literals, (iv) via modifying an instance of 'Object'.

In general, the approach to Objects in JavaScript is highly dynamic, in part due to the nature of JavaScript being interpreted. By being an interpreted language elements that - in many languages - would happen at compile-time instead happen at run-time in JavaScript

The following section will demonstrate how to define and instantiate objects in JavaScript, using the aforementioned methods:

 

Classes

class Car {
  make = '';
  model = '';
  motor;

  constructor(make, model, motor) {
    this.make = make;
    this.model = model;
    this.motor = motor;
  }
}

class MotorEngine {
  noOfCylinders = 0;
  manufacturer = '';

  constructor(noOfCylinders, manufacturer) {
    this.noOfCylinders = noOfCylinders;
    this.manufacturer = manufacturer;
  }
}

myCarInstance = new Car('BMW', '320i', new MotorEngine(4,'BMW'));

 

Constructor Functions

function Car() {
    this.make = 'BMW',
    this.model = '318 IS',
    this.colour 'black',
    this.engine = {
        noOfCylinders: 4,
        manufacturer: 'BMW'
    }

}

const myCarInstance = new Car();

 

Object Literal

const myCarInstance = { 
    make: 'BMW',
    model: '318 IS',
    colour: 'black',
    engine: {
        NoOfCylinders: 4,
        Manufacturer: 'BMW'
    }
};

 

Modifying an Instance of Object

const myCarInstance = new Object ({ 
    make: 'BMW',
    model: '318 IS',
    colour: 'black',
    engine: {
        NoOfCylinders: 4,
        Manufacturer: 'BMW'
    }
});

 

As you can see, there are a variety of ways of defining classes, an interesting note is that many of these methods instantiate an instance during the definition.

Prototypes-based Inheritance

Inheritance is an important feature of OO languages and design, this is discussed in our article on Object Orientation. Inheritance in JavaScript is implemented via a mechanism called Prototypes. Every object in JavaScript has a prototype, and it carries the various methods/functions and properties for a given object.

There are a number of ways of accessing a prototype, and this is not entirely standardised:

  • Most browsers support the __proto__ property on an instance
  • Most browsers also support the prototype property on an instance or the class
  • The more official approach is to use the Object.getPrototypeOf()function/method.

All three approaches return the same thing, the following screenshot shows the result in Firefox:

Date.prototype

It is possible to dynamically alter a prototype at runtime, thereby adding new properties or methods to all instances of that type. 

For example, the following code will add a new method to all instances of Date:

Date.prototype.aNewMethod = function() { console.log("Hello World"); };

Thus, if we create instances of the Date class, we can then execute this new method, i.e. modifying the prototype affects all instances of Date:

Date.prototype.aNewMethod = function() { console.log("Hello World"); };

myDate = new Date();
myDate.aNewMethod();

The effect of this is shown in the following screenshot:

Adding a new method to a prototype

Whereas, if a new method, or function, is added to an instance it will only be available in that specific instance.

The following code demonstrates the contrast:

// Create the instances
myDate = new Date();
mySecondDate = new Date();

// Define the new methods/functions
// 1. on the prototype
Date.prototype.aNewMethod = function() { console.log("Hello World"); };
// 2. on a specific instance
myDate.anotherNewMethod = function() { console.log("Instance Only"); };


// Attempt to call the methods
myDate.aNewMethod(); // works
myDate.anotherNewMethod(); // works
mySecondDate.aNewMethod(); // works
mySecondDate.anotherNewMethod(); // error

The following screenshot shows the output in Mozilla FireFox:

Comparison between adding functions to a prototype and an instance

Conclusion

JavaScript supports Object Oriented programming and design, with multiple ways of defining and instantiating objects (with these two concepts often merged).

Due to its interpreted nature, the items such as class definition happen at runtime as opposed to during compilation, and additionally, it has a powerful - and possibly unique - method for enabling inheritance and manipulating entire classes of object through its prototypes.

Chris Blake

About the author

https://www.linkedin.com/in/chrisblake/

Chris Blake has over 20 years of experience in the information and cyber security field, and is a passionate and qualified Enterprise Security Architect and Privacy Professional who leads and delivers innovative solutions at Firesand Limited, a company he co-founded in 2016. His specialities include application security, enterprise security architecture, and privacy, with a strong track record of building and implementing ISO 27001 compliant and certified information security practices, application security programmes, and enterprise security architectures. He has a thirst for continual learning and a commitment to excellence, as demonstrated by his academic and professional credentials from prestigious institutions such as the University of Oxford, (ISC)², IAPP, SABSA, The Open Group, and ISACA.

Chris holds an MSc in Software and Systems Security at the University of Oxford, and an array of professional certifications: CISSP, ISSAP, CSSLP, CCSP, SSP.NET, SSP.JAVA, CISA, CISM, CIPP/E, CIPM, CIPT, FIP, SCF, TOGAF, CPSA, and CEH.

Chris' experience spans multiple sectors: Retail & eCommerce; Financial Services, Banking, & Payments; i-Gaming; Energy (Oil & Gas); Property Management & PropTech; and Data Science; as well as Defence. 

His areas of interests include: penetration testing; regulation & privacy, including the impact on society; access control in software; security automation in development; application of cryptography; security architecture; risk modelling & analysis; HTTP architecture & web security; IoT Security.

Cookie Notice

We use cookies to ensure that we give you the best experience on our website. Please confirm you are happy to continue.

Back to top