Constructor Functions and the new Operator
In this lecture, let's finally implement object-oriented programming 🎉 starting with constructor functions. So, let's get started!
We actually kind of used object-oriented programming before but in a very limited way. Because we had no way of programmatically creating objects, hence, all we did was to use some simple object literals. But now, with constructor functions, everything changes.
So, we can use constructor functions to build an object using a function. And a constructor function is just a completely normal function. The only difference between a regular function and a constructor function is that we use the new
operator to call a constructor function. Enough talk; let's see it in action 🔥.
Let's say we want to create a constructor function for a person object.
const Person = function () {};
Before we move on, there are three things I want to point out.
Array
, or Map
, follow this convention as well.this
keyword.Remember that our constructor function is going to produce an object and, in this case, a person object. So, we need to add some properties to this object. So, let's says our person object needs to have a firstName
, a lastName
, a birthYear
, and a profession
.
const Person = function (firstName, lastName, birthYear, profession) {};
Let's now call this constructor function! Don't forget to use the new
operator 😉
const Person = function (firstName, lastName, birthYear, profession) {
// Do something...
};
new Person('Evan', 'Guerrero', 1992, 'Developer');
The new
operator is actually very special. And it does more than just calling the function. So let's see what happens when we call a constructor function using the new
operator 🕵️♂️.
Behind the scenes, the new
operator does four things:
{}
.this
keyword is set to point to the newly created empty object (this = {}
).==> {}
). At this point, the object no longer needs to be empty.So, let's get into our constructor function and log the this
keyword.
const Person = function (firstName, lastName, birthYear, profession) {
console.log(this);};
new Person('Evan', 'Guerrero', 1992, 'Developer');
From the steps above, we know that the this
keyword is going to point to the newly created empty object.
Let's now use this knowledge to our advantage. We already know that at the end of the constructor function, the this
will be returned. Hence, whatever we add to that empty object, will then be returned from the function. And that returned object will be the object we are going to build in our constructor function. So, all we need to do is to add some properties to the this
keyword.
const Person = function (firstName, lastName, birthYear, profession) {
/**
* The property names don't have to be the same as the parameter names.
* We can use any name we want. It's just a convention to use the same name.
*/
this.firstName = firstName; this.lastName = lastName; this.birthYear = birthYear; this.profession = profession;};
const evan = new Person('Evan', 'Guerrero', 1992, 'Developer');
console.log(evan);
Great! We now have our person object with all the properties set, and each property is set to the value that we passed into the constructor function. Let's recap what we just did.
new
keyword.this
keyword was set newly created empty object.this
keyword. Hence, at the end of the function, the this
keyword now has four new properties.evan
).We can now use this constructor function to create as many person objects as we want. Let's actually create a few more person objects.
// The blueprint
const Person = function (firstName, lastName, birthYear, profession) {
//...
};
// The actual objects
const alfred = new Person('Alfred', 'Medina', 1990, 'Designer');
const rodney = new Person('Rodney', 'Dennis', 1994, 'Architect');
console.log(alfred);
console.log(rodney);
And indeed, we now have each object on its own, created programmatically using the same constructor function. Now, remember from one of the previous lectures that in classical OOP, an object created from a class is called an instance. In our scenario, we didn't technically create a class here because, as we discussed before, JavaScript doesn't really have classes in the sense of traditional OOP.
However, we did create an object from a constructor function (actually three). And constructor functions have been used since the beginning of JavaScript to kind of simulate classes. Hence we can still say that evan
for example, is an instance of Person
.
There is actually an operator called instanceof
that we can use to check if an object is an instance of a constructor function. Let's see it in action.
console.log(evan instanceof Person); // true
console.log(alfred instanceof Person); // true
Since we are currently talking about instances, we can also say that the properties we define in our constructor function are called instance properties. And that's because each instance of the constructor function will have it's own copy of those properties.
const Person = function (firstName, lastName, birthYear, profession) {
// Instance properties
this.firstName = firstName;
//...
};
Next, how do we add methods to our constructor function? Well, just like we added properties, we can, of course, also add methods. Let's add a method called calcAge
to our constructor function.
const Person = function (firstName, lastName, birthYear, profession) {
// Instance properties
this.firstName = firstName;
//...
this.calcAge = function () { console.log(2024 - this.birthYear); };};
This would work just fine here, but this is a really bad practice! Never do this! Never add methods to the constructor function. Why? Imagine we need to create thousands or tens of thousands of person objects. This means that each of these objects will carry around a copy of the calcAge
method. And that's a lot of unnecessary memory usage, and also, it's bad for performance. To solve this problem, we are going to use prototypes and prototype inheritance.
To finish this lecture, just note that function constructors are not really a feature of the JavaScript language. Instead, they are simply a pattern that has been developed by other developers, and now everyone simple uses it 😅. And this now includes you as well 😂.