DEV Community

Cover image for OOP: From Pseudo-classical class instantiation to Class instantiation
Diego Villa
Diego Villa

Posted on

OOP: From Pseudo-classical class instantiation to Class instantiation

In this post, we will discuss how we can create objects in JavaScript. We will explore the traditional approach using Pseudo-classical class instantiation and will end with Class instantiation introduced in ECMAScript 6.

Introduction to objects

Objects are key/value pairs to store information about an entity that we can to represent in our code. You can create an object using the curly braces {}, and you can add properties and methods using the dot notation.

let employee = {};

// Properties
employee.name = 'Diego';
employee.position = 'Software Engineer';

// Methods
employee.program = function () {
  console.log(`${this.name} is programming!`);
};

employee.program(); // Result: Diego is programming!
Enter fullscreen mode Exit fullscreen mode

Functional instantiation

To create multiple objects we can use a constructor function. A constructor function encapsulates an object creation and it allows you to create multiple instances of the same object structure.

Creating a constructor function to instantiate new objects follows the functional instantiation pattern.

function Employee(name, position) {
  let employee = {};
  employee.name = name;
  employee.position = position;

  employee.program = function() {
    console.log(`${this.name} is programming!`);
  };

  return employee;
}

const employeeDiego = Employee('Diego', 'Software Engineer');
const employeeJuan = Employee('Juan', 'Sofware Architect');
Enter fullscreen mode Exit fullscreen mode

Functional instantiation with shared methods

Every time that we are creating a new instance of the Employee object we are creating, in memory, something like this:

const employeeDiego = {
  name: 'Diego',
  position: 'Software Engineer',
  program: [Function],
};

const employeeJuan = {
  name: 'Juan',
  position: 'Software Architect',
  program: [Function],
};
Enter fullscreen mode Exit fullscreen mode

We can observe that we are creating two objects that share the same functionality (program). If we are creating two objects we probably didn't see the memory impact, but if we are creating thousands of objects we are wasting memory to store every time the same functionality. To avoid this problem we can use functional instantiation with shared methods.

const employeeMethods = {
  program: function() {
    console.log(`${this.name} is programming!`);
  }
};

function Employee(name, position) {
  let employee = {};
  employee.name = name;
  employee.position = position;
  employee.program = employeeMethods.program;

  return employee;
}

const employeeDiego = Employee('Diego', 'Software Engineer');
const employeeJuan = Employee('Juan', 'Sofware Architect');
Enter fullscreen mode Exit fullscreen mode

With this improvement we will creating, in memory, something like this:

const employeeDiego = {
  name: 'Diego',
  position: 'Software Engineer',
  program: [Function: program],
};

const employeeJuan = {
  name: 'Juan',
  position: 'Software Architect',
  program: [Function: program],
};
Enter fullscreen mode Exit fullscreen mode

In JS objects are passed as reference, so we only have created a single object that encapsulates the program function, and every instance of the Employee object access the same function in memory.

Object.create

We can improve our constructor function using Object.create.

const employeeMethods = {
  program: function() {
    console.log(`${this.name} is progamming`);
  }
};

function Employee(name, position) {
  let employee = Object.create(employeeMethods);
  employee.name = name;
  employee.position = position;

  return employee;
}

const employeeDiego = Employee('Diego', 'Software Engineer');
const employeeJuan = Employee('Juan', 'Sofware Architect');
Enter fullscreen mode Exit fullscreen mode

With this improvement, every time we create a new instance of the Employee object we will have, in memory, something like this:

const employeeDiego = {
  name: 'Diego',
  position: 'Software Engineer',
};

const employeeJuan = {
  name: 'Juan',
  position: 'Software Architect',
};
Enter fullscreen mode Exit fullscreen mode

If the created objects don't have the program method, how will it be possible to invoke it? Every time we invoke employee.program() will fail because the created object doesn't have that method. But we use Object.create(employeeMethods), so every time we invoke the program method it will look it in the parent object (employeeMethods).

Prototypal instantiation

In JavaScript, every function has a prototype property that references an object. This property allows us to share methods across all instances of a function.

function Employee(name, position) {
  let employee = Object.create(employeeMethods);
  employee.name = name;
  employee.position = position;

  return employee;
}

console.log(Employee.prototype); // Employee {} 
Enter fullscreen mode Exit fullscreen mode

So, we can use the prototype property to share the program function across all instances instead of using a separate object.

function Employee(name, position) {
  let employee = Object.create(Employee.prototype);
  employee.name = name;
  employee.position = position;
}

Employee.prototype.program = function () {
  console.log(`${this.name} is programming`);
};

const employeeDiego = Employee('Diego', 'Software Engineer');
Enter fullscreen mode Exit fullscreen mode

With this improvement, every time we create a new instance of the Employee object we will have, in memory, something like this:

const employeeDiego = {
  name:  'Diego',
  position: 'Software Engineer',
};
Enter fullscreen mode Exit fullscreen mode

And the Employee.prototype will look like:

{
  program: [Function]
}
Enter fullscreen mode Exit fullscreen mode

Pseudo-classical class instantiation

Currently, we are using the Object.create() function to create a new object based on the prototype of a parent object, and then we return that created object. With the new keyword, we can merge the Object.create() and return functionality. The created object is called this.

function Employee(name, position) {
  this.name = name;
  this.position = position;
}

Employee.prototype.program = function () {
  console.log(`${this.name} is programming`);
};

const employeeDiego = new Employee('Diego', 'Software Engineer');
Enter fullscreen mode Exit fullscreen mode

This pattern is called pseudo-classical class instantiation. When we use the new keyword we are invoking the function constructor. If we don't add the new keyword, the function won't create the object and it will return undefined.

Class instantiation

With ECMAScript 6 a class keyword was added. The class keyword was introduced to create classes in popular OOP programming languages like Java, but it works as the pseudoclassical class instantiation.

class Employee {
  constructor(name, position) {
    this.name = name;
    this.position = position;
  }

  program() {
    console.log(`${this.name} is programming!`);
  }
}

const employeeDiego = new Employee('Diego', 'Software Engineer');
Enter fullscreen mode Exit fullscreen mode

Photo by Lucas Benjamin on Unsplash

Top comments (0)