JavaScript: Constructor Functions

Creating Objects with Constructor Functions & The ‘new’ Operator

Jake Mills
May 6 · 5 min read
Photo by Ben Allan on Unsplash

Last week, I touched on the subject of factory functions. As promised, this week, I want to take the same factory we created and mutate it into a constructor function and create instances of the object with the new operator.

Before diving into mutating the factory function into a constructor function, here’s a little excerpt by Eric Elliot talking about the differences between the two:

What’s the Difference Between a Factory and a Constructor?

Constructors force callers to use the new keyword. Factories don’t. That’s it, but that has some relevant side-effects.

So what does the new keyword do?

Note: We’ll use instance to refer to the newly created instance, and Constructor to refer to the constructor function or class that created the instance.

1. Instantiates a new instance object and binds this to it within the constructor.
2. Binds instance.__proto__ to Constructor.prototype.
3. As a side-effect of 2, binds instance.__proto__.constructor to Constructor.
4. Implicitly returns this, which refers to instance.

Eric Elliot, JavaScript Factory Functions vs Constructor Functions vs Classes

Now, let’s get to it.

Constructor Functions

In class-based object-oriented programming, a constructor (abbreviation: ctor) is a special type of subroutine called to create an object. It prepares the new object for use, often accepting arguments that the constructor uses to set required member variables.

Wikipedia

To get us started, let’s put our factory function from last week below for reference:

const makeHero = (name, alias, abilities) => {
const hero = {};
hero.name = name;
hero.alias = alias;
hero.abilities = abilities;
hero.assemble = function () {
avengers.includes(this)
? console.log(
`${this.alias} has already been assembled into the
Avengers`
)
: avengers.push(this);
return avengers;
};
hero.disassemble = function () {
const heroToRemove = avengers.findIndex(
(hero) => hero === this
);
heroToRemove === -1
? console.log(
`${this.alias} has already been disassembled from the
Avengers`
)
: avengers.splice(heroToRemove, 1);
return avengers;
};
return hero;
}

The factory function above creates an object and then returns that object. Let’s take a look at an example of a constructor function from MDN:

function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}

You’ll notice that the object is never set to a variable within the function, nor is anything set to return from the function. So, how does this work? Enter the new operator. The new keyword has some JS magic working behind the scenes and empowers the creation of instances of the objects through the following steps:

1. Creates a blank, plain JavaScript object.
2. Adds a property to the new object (__proto__) that links to the constructor function's prototype object
3. Binds the newly created object instance as the this context (i.e. all references to this in the constructor function now refer to the object created in the first step).
4. Returns this if the function doesn't return an object.

MDN

You’ll see above that in step 1, the new keyword ‘creates a blank, plain JavaScript object,’ and in step 4, ‘returns this if the function doesn’t return an object.’ That’s why we don’t have to hard code a new object set to a variable and return that object as we do in a factory function. With just a few minor tweaks, we have our constructor function below:

function Hero(name, alias, abilities){
this.name = name;
this.alias = alias;
this.abilities = abilities;
this.assemble = function () {
avengers.includes(this)
? console.log(
`${this.alias} has already been assembled into the
Avengers`
)
: avengers.push(this);
return avengers;
};
this.disassemble = function () {
const heroToRemove = avengers.findIndex(
(hero) => hero === this
);
heroToRemove === -1
? console.log(
`${this.alias} has already been disassembled from the
Avengers`
)
: avengers.splice(heroToRemove, 1);
return avengers;
};
}

That’s the factory function we made before but as a constructor function. If we want to create a new instance of our Hero, we will declare it like this:

const captainAmerica = new Hero('Steven Rogers', 'Captain America', ['Enhanced strength, speed, stamina, durability, agility, reflexes, senses, and mental processing via the super soldier serum',
'Master martial artist and hand-to-hand combatant',
'Accelerated healing',
'Immunity to diseases and toxins',
'Slowed aging',
'Master tactician, strategist, and field commander',
'Using Vibranium-steel alloy shield']);

It's very similar to what we did before with the factory function, but now we use the new keyword to create the instance.

One last thing. If we compare two instances of the object and the functions included within the factory function (assemble & disassemble) you’ll notice that they are not equal.

captainAmerica.assemble === captainMarvel.assemble
// false

Every time a new object is created, it is given these functions as unique functions to the object's instance. With constructor functions, we can avoid these functions being created uniquely to the objects by using the prototype property. Creating those same functions so our Hero constructor has access to them through the prototype chain would look like this:

Hero.prototype.assemble = function() {
avengers.includes(this)
? console.log(
`${this.alias} has already been assembled into the
Avengers`
)
: avengers.push(this);
return avengers;
};

Then if you compare the functions now, as we did before, you will get true!

captainAmerica.assemble === captainMarvel.assemble
// true
assemble & disassemble are part of the prototype chain for Hero

Our finalized constructor function, formerly a factory function, now looks like this:

Constructor functions give us the opportunity of using the new keyword to create objects. Factory functions do mostly the same thing but don’t use the keyword new. Next week we’ll cover the final mutation of our function into a class.

Happy Coding 🤓

Geek Culture

Proud to geek out. Follow to join our +500K monthly readers.

Jake Mills

Written by

Software Engineer hailing from the Empire State, writing about what interests me and hoping someone else finds it interesting too. 👨🏻‍💻 🤓 He/Him #LFGM

Geek Culture

A new tech publication by Start it up (https://medium.com/swlh).

Jake Mills

Written by

Software Engineer hailing from the Empire State, writing about what interests me and hoping someone else finds it interesting too. 👨🏻‍💻 🤓 He/Him #LFGM

Geek Culture

A new tech publication by Start it up (https://medium.com/swlh).

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store