Making Object Instances in JavaScript

Part 1: Initializers and Functional Instantiation Patterns—which way, which way… a few pointers to help you decide.

Kamie Robinson
4 min readJul 17, 2017

In JavaScript, there are several ways to use object initializers and make an object instance, from writing an object literal, to functional instantiation patterns, to ES6 classes and subclassing. Knowing how to implement every possible way is commendable. Having a solid reason why you choose a particular way gets respect.

If you are not sure about the different instantiation options or which one to choose, this two-post series provides an overview of things to consider as you decide.

This first post covers common initializers and functional instantiation patterns. A follow up post will go over ES6 classes.

Initializers

Just about everything in JavaScript is an Object, including arrays and functions. Since talking about the whole language is out of scope for this, I will focus on two common initializers used: an object literal and Object.create().

Object Literal

Literally typing code line-by-line to create an instance of an object

var groot = {
speakCount: 0,
speak: function() { obj.speakCount++; return 'I am Groot.'; }
}

Object literal notation, sometimes called initializer notation, is not considered an instantiation pattern by itself because it can not produce more similar instances. If you would like a second, or third… instance, you have to type it out character-by-character or copy, paste and edit. For class-like situations, it is not maintainable, but the advantage is that you can quickly create objects with properties.

Object literals are a good option when:

  • Writing an example of what an instantiation pattern should produce
  • Only one instance is needed
  • Declaring an object inside a function — e.g. when you generate an object in the functional instantiation pattern (see the instantiation patterns table below)

Object.create()

Creates an object instance and delegates failed lookups to specified prototype

//CONSTRUCTOR
var Groot = function() {
var obj = Object.create(Groot.prototype);
return obj;
}
//PROTOTYPE
Groot.prototype.speak = function() { return 'I am Groot.';}

Object.create() is used to change the prototype from the default Object prototype, to a custom object. If an object doesn’t have a property, it will delegate to its prototype to see if the prototype has the property. If it does, the object instance will use the property value from the prototype.

Object.create’s second parameter allows you to add properties

//CONSTRUCTOR
var Groot = function() {
var obj = Object.create(Groot.prototype, grootsJob);
return obj;
}
//PROTOTYPE
Groot.prototype.speak = function() { return 'I am Groot.';}
//ADDITIONAL PROPERTY
var grootsJob = {
occupation: {
value: 'Guardian of the Galaxy',
writable: true,
configurable: true
}
}
//CREATE A NEW INSTANCE AND LOG 'Guardian of the Galaxy'
var branch = Groot();
console.log(branch.occupation);

Object.create() is a good option when:

  • Objects should share properties, but not store the individual properties, or references to them, in each instance of the object
  • A prototype, other than the default object prototype, should be referenced to look for failed lookups
  • Declaring an object in a prototypal instantiation pattern (see the instantiation patterns table below)

Functional, Prototypal and Pseudoclassical Instantiation Patterns

functions written to create object instances with properties

Four types of factory-function object instantiation patterns are often referenced: functional, functional-shared, prototypal, and pseudoclassical. The table below from Ryan Atkinson’s post, JavaScript Classes and Instantiation Patterns, clearly outlines the structure of each.

A helpful table from Ryan Atkinson post, JavaScript Classes and Instantiation Patterns, http://www.ryanatkinson.io/javascript-instantiation-patterns/

When should each pattern be used?

Functional instantiation when:

  • Updating values without affecting other instances is considered good. This works because all properties are saved for each instance. It also ensures methods are called on the intended object, meaning no need to use this or binding.
  • Readability is important. It is easy to see an object’s properties.
  • Memory is not an issue.

Functional Shared Instantiation when:

  • Several object instances should reference shared properties
  • NOTE: shared references are copied ONCE when the object is created. If a shared property is edited, all instances will reference the updated methed or value, BUT if a new shared property is added, instances made prior to it being added will never be able to access the new property
  • NOTE: In shared methods, the this keyword needs to be used

Prototypal Instantiation when:

  • Shared properties may continually be added and updated and all object instances should be able to reference the updates. Prototypal instantiation makes use of Object.create() so shared properties can be accessed through lookup delegation.

Pseudoclassical Instantiation when:

  • Benefits of prototypal delegation is wanted
  • Efficiency matters
  • Less readability is okay, because engineers are familiar with the pattern and know that when instantiating with the new keyword, the interpreter takes care of generating the object and returning it.

--

--

Kamie Robinson

Software Engineer rooted as a Creative. Writing how-tos and about 'ahas' and 'gotchas' of making.