Skip to main content Accessibility Feedback

Constructor patterns vs. plain objects vs. traditional functions

In yesterday’s article on creating your own vanilla JS DOM manipulation library, I wrote…

With a DOM manipulation, we want to get elements from the DOM and call methods on them. To make that work, instead of returning an object we want to return a constructor pattern.

One of my readers wanted to know when and why you would use a constructor pattern vs. a plain object vs. a function.

Let’s dig in!

Plain Objects

Plain objects (sets of key/value pairs wrapped in {}) are great for storing simple data sets.

var lunch = {
	sandwich: 'turkey',
	drink: 'soda',
	chips: true
};

var party = {
	theme: 'pirates',
	snacks: ['chips', 'cookies', 'ice cream'],
	drinks: ['soda', 'water', 'juice']
};

// Returns "pirates"
party.theme;

Most of the time, this is a great choice. Here’s a demo.

Functions with properties

Because everything is an object in JavaScript, you could also assign named properties to a function instead of using a plain object.

(This is why {} objects are called “plain objects.” It differentiates them from every other object type in JavaScript. Yea, it’s confusing!)

var lunch = function () {
	return 'I would like a ' + lunch.sandwich + ' sandwich, with ' + lunch.drink + ' to drink.' + (lunch.chips ? 'Also, chips please.' : '');
};
lunch.sandwich = 'turkey';
lunch.drink = 'soda';
lunch.chips = true;

// Returns "I would like a turkey sandwich, with soda to drink. Also, chips please."
lunch();

This type of pattern let’s you attach data to a function, and then run it to do something with that data. It’s a simple way to setup one-off state-based components.

Here’s a demo of this in action.

Constructor patterns

A constructor pattern let’s you create a new object type. This object type can be used to create new JavaScript objects that have unique values or data, but share a set of properties.

For example, let’s say you had a restaurant app and wanted to submit multiple lunch orders. You might create a Lunch constructor (constructor names are title-cased) that holds the order details.

var Lunch = function (sandwich, drink, chips) {
	this.sandwich = sandwich;
	this.drink = drink;
	this.chips = chips;
};

Then, you can create new orders by instantiating new instances of Lunch() with the unique data for each lunch order.

var customer1 = new Lunch('turkey', 'soda', true);
var customer2 = new Lunch('tuna', 'water', false);

// Returns "soda"
customer1.drink;

// Returns "tuna"
customer2.sandwich;

You can also attach functions to the constructor’s prototype. It can access the unique properties for each instance using this.

Lunch.prototype.getOrder = function () {
	return 'I would like a ' + this.sandwich + ' sandwich, with ' + this.drink + ' to drink.' + (this.chips ? 'Also, chips please.' : '');
};

// Returns "I would like a turkey sandwich, with soda to drink. Also, chips please."
customer1.getOrder();

// Returns "I would like a tuna sandwich, with water to drink."
customer2.getOrder();

Here’s the constructor pattern in action.

Different patterns for different use cases

Each pattern has it’s own set of situations where its useful, and a whole bunch where it’s not.

If you don’t need to hold unique data or create multiple items with the same properties (but different values), then the constructor pattern is over-engineered and adds no value, for example.