Sitemap
Will Resen

Will Resen

Software engineer, session musician and private instructor.

Introduction to Object-Oriented Programming in JavaScript

4 min readMay 17, 2019

Object-Oriented Programming is a fundamental paradigm of the JavaScript language that offers simplicity when working with a wide range of data structures. OOP provides an efficient means for keeping track of data by allowing programmers to create independent modules that contain their own properties and methods. Prototypal inheritance allows these methods and properties to be shared between similar objects. This article will discuss the strengths and weaknesses of the various ways to create objects in JavaScript — let’s begin!

An object literal is the simplest form of an object:

var object = {};

Within it we may add properties that consist of key-value pairs:

var object = {
'key1': 'value1',
'key2': 'value2'
};

Although keys will always be coerced as strings, values have no such restriction:

var object = {
'key1': function(parameter){ console.log("Hello World!") },
'key2': {'key': 'value'};
};

Object literals are a fast and easy way to quickly store data, but what if we want multiple objects that have similar features?

Typing everything manually would be quite tiresome:

var guitar1 = {
'manufacturer': 'Gibson',
'model': 'ES-335',
'year': 1958
};
var guitar2 = {
'manufacturer': 'Fender',
'model': 'American Deluxe Telecaster',
'year': 2019
};
var guitar3 = {
'manufacturer': 'Martin',
'model': 'HD-28V',
'year': 2016
};
//repeat ad infinitum...

Fortunately, to reduce our workload, JavaScript gives us the ability to utilize classes. Classes are any construct capable of producing similar objects that conform to the same interface. In other words, classes provide an easy way to create objects that share properties and methods. These objects, called instances of a class, are created by a constructor function. Creating an instance of a class by calling a constructor function is called instantiating, and JavaScript has four primary instantiation patterns:

  1. Functional Instantiation
  2. Functional-Shared Instantiation
  3. Prototypal Instantiation
  4. Pseudoclassical Instantiation

Let’s discuss each of these patterns and their relative strengths and weaknesses.

Functional instantiation consists of a function that creates an object, adds properties and methods, and then returns the object.

function Guitar(manufacturer, model, year){
var object = {};
object.manufacturer = manufacturer;
object.model = model;
object.year = year;
object.play = function(){ console.log("Let's rock!") };
return object;
};
var myGuitar = Guitar("Gibson", "ES-335", 1958);
console.log(myGuitar.model); //will return "ES-335"

Note how the first letter of the function’s name is capitalized — this signals that we are creating a class.

Get Will Resen’s stories in your inbox

Join Medium for free to get updates from this writer.

Every time the above function is called, the data contained within it is duplicated. Thus, the new objects have methods that point to different functions regardless of if they are identically written. Although the previous example involves an object with only simple properties and a single method, objects in larger applications will likely use more memory. To save space, an alteration must be made to prevent the unnecessary duplication of methods.

Functional-shared instantiation alters functional instantiation to avoid duplicating methods upon each new object’s creation. It utilizes a property attached to the constructor function that contains the shared methods as well as an extend function that copies the methods to the new object.

function Guitar(manufacturer, model, year){
var object = {};
object.manufacturer = manufacturer;
object.model = model;
object.year = year;
extend(object, Guitar.methods);
return object;
};
function extend(object, methods){
for(let key in methods){
object[key] = methods[key];
}
};
Guitar.methods = {
'play': function(){ console.log("Let's rock!") },
'shred': function(){ console.log("Diddly Diddly!") },
'hendrix': function(){ console.log("Wah Wah!") }
}
var myGuitar = Guitar("Gibson", "ES-335", 1958);
myGuitar.shred(); //will log "Diddly Diddly!"

The next two instantiation patterns utilize the prototype chain that allows an object to inherit properties from another. All objects in JavaScript eventually delegate failed property lookups to the Object prototype, a property of the Object constructor that contains the shared properties of all objects in the language. This delegation of failed property lookups is called inheritance.

myGuitar.toString(); //will return [object Object]

Even though toString was not defined as a property in Guitar.methods, it still runs without error. When a property does not exist on an instance of the constructor function, the lookup then ‘falls through’ to the prototype object to check if the property exists there. If it does, our new object then inherits the property.

Prototypal instantiation uses Object.create() to instantiate a new object that passes failed lookups up the prototype chain to a specified parent object.

var instrument = {
'play': () => console.log("Let's rock!"),
'practice': () => console.log("Getting better..."),
'record': () => console.log("Testing... 1, 2, 3.")
}
function Guitar(manufacturer, model, year){
var object = Object.create(instrument);
object.manufacturer = manufacturer;
object.model = model;
object.year = year;
return object;
};
var myGuitar = Guitar("Fender", "Stratocaster", 2019);
myGuitar.practice(); //will log "Getting better..."

Although prototypal instantiation is a step closer to finding an ideal instantiation pattern, there is still one more to cover.

Pseudoclassical instantiation is intended to reduce the amount of typing used in prototypal instantiation. It uses the new and this keywords to respectively create and add properties to an object. Methods are added directly to the constructor function by means of the prototype object, a property which is automatically created for every function.

function Guitar(manufacturer, model, year){
this.manufacturer = manufacturer;
this.model = model;
this.year = year;
}
Guitar.prototype.play = () => console.log("Let's rock!");
Guitar.prototype.practice = () => console.log("Getting better...");
Guitar.prototype.record = () => console.log("Testing... 1, 2, 3.");
var myGuitar = new Guitar("Gibson", "ES-335", 1958);
myGuitar.play(); //will log "Let's rock!"

As a reminder, new properties may also be added directly to an instance without affecting other objects of the same class:

myGuitar.previousOwner = "Eric Johnson";
console.log(myGuitar.previousOwner); //will log "Eric Johnson"
var newGuitar = new Guitar("Fender", "Telecaster", 2019);
console.log(newGuitar.previousOwner); //will log undefined

With these methods of instantiation, you’re ready to conquer the world of object-oriented programming!

For extra practice, try creating an inventory for a local store. What kind of products do they have? Which properties will their respective objects share, and which ones will differ?

--

--

Will Resen
Will Resen

Written by Will Resen

Software engineer, session musician and private instructor.