JavaScript Factory functions vs Constructor functions.

When it comes to the JavaScript Language comparing to other programming languages there are lots of words that you may hear or see really confusing to understand. One of them would be factory functions and the constructor functions.

Without further do let’s start with a definition for the factory functions.

Factory functions

function person(firstName, lastName, age) {
const person = {};
person.firstName = firstName;
person.lastName = lastName;
person.age = age;
return person;
}

If you look at the above code inside the function, it creates a new object and attached passed arguments to that object as properties to that and return the new object. That is a simple factory function in JavaScript. Now let’s look at what is a Constructor function in JavaScript.

Constructor Functions

function Person(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

Creating Objects with new Keyword

  1. Can’t we use the new keyword with factory functions?
  2. What happens if we used new keyword with factory and constructor functions?
  3. What happens if we don’t use new keyword when creating object instances using constructor functions?

Okay, let’s try to find answers to the above questions. Before that let’s do a small exercise to understand what is going on.

Let’s create two objects using new keyword using both factory and constructor functions and then let’s console.log those created object to the console separately.

Using factory function:

function person(firstName, lastName, age) {
const person = {};
person.firstName = firstName;
person.lastName = lastName;
person.age = age;
return person;
}
const mike = new person('mike', 'grand', 23);

As we can see in the above console log I’ve expanded the __proto__ which is a pointer to its prototype object. And let’s try to find out whose prototype object is this. I hope you are familiar with JavaScript prototype concepts and if not feel free to have a look at my article on JavaScript prototypes. In order to find out the pointing prototype object of above mike object lets do simple === equality checks.

Hmmm, interesting that is the Object’s prototype. Okay then let's do the same set of experiments with the constructor function.

Using constructor function:

Note: In JavaScript, these constructor functions are also called as constructors as they are used to create Objects.

function Person(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
const mike = new Person('mike', 'grand', 23);

As we expand the __proto__ of the mike it also has another __proto__ inside it, Let’s expand that as well.

And now let's try to figure out whose prototype objects are those as we did before.

Oh, they are different. When we are creating objects using factory function its __proto__ points to the Object.prototype whereas when creating objects from constructor functions it points to its constructor function prototype object. So what is happening here?

Behind the scene of 'new' operator

The new operator lets developers create an instance of a user-defined object type or of one of the built-in object types that has a constructor function.

More info : MDN Documentation new operator

That is the definition of the new keyword in the MDN documentation, that is this keyword has introduced to use constructor function even though you can use it with factory functions. But if we use the new keyword with constructor function there are few things happens behind the scene, that is JavaSript engine will do few things for us when we are creating objects. That is It adds some implicit code that we don’t see. Let me explain what is happening behind the scenes using simple pseudocode. The commented lines are pseudocode representing functionality that is implicitly added by the JavaScript engine when using new with a constructor function.

function Person(firstName, lastName, age) {
// this = {};
// this.__proto__ = Person.prototype;
// Set up logic such that: if
// there is a return statement
// in the function body that
// returns anything EXCEPT an
// object, array, or function:
// return this (the newly
// constructed object)
// instead of that item at
// the return statement;
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
// return this;
}

Basically following are the what is happening behind the scene. Which are not visible to us.

  1. Creates a new object and binds it to the this keyword.
  2. Sets the object’s internal [[Prototype]] property, __proto__, to be the prototype of the constructing function. (And also note that this also makes it so the constructor of the new object is prototypically inherited.)
  3. Sets up logic such that if a variable of any type other than object, array, or function is returned in the function body, return this, the newly constructed object, instead of what the function says to return.
  4. At the end of the function, returns this object if there is no return statement in the function body.

And also let’s see what happens if we add the above implicit code to our factory function.

function person(firstName, lastName, age) {    // this = {};
// this.__proto__ = Person.prototype;

// Set up logic such that: if
// there is a return statement
// in the function body that
// returns anything EXCEPT an
// object, array, or function:
// return this (the newly
// constructed object)
// instead of that item at
// the return statement;
const person = {};
person.firstName = firstName;
person.lastName = lastName;
person.age = age;
return person;
// return this;
}

Even though implicit code added to the factory function when invoking with the new keyword, there will be a zero effect on the outcome. That is because since we are not using this keyword inside the function and we are explicitly returning a custom object other than the this , there will be no use of having the implicit code. Simply put there has no effect on the output whether we use new keyword or not with the factory functions.

What if you forget ‘new’ keyword?

In JavaScript,

  • You can use new operator on ANY function
  • You can call function intended as constructor WITH or WITHOUT the new keyword

Let’s look at the same example as above with and without the new keyword now.

function Person(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
const mike = new Person('mike', 'grand', 23);
const bob = Person('bob', 'grand', 23);

Then if you look at the created object instances what would you expected to see?

With and Without new operator.

What did happen? It looks like as we expected with the new operator, it outputs the correct object, but without the new operator the result is undefined. So how is that possible?

If you have an idea about how the JavaScript Scope and this keyword works in JavaScript probably you can guess what has happened here? Let’s see.

Changes are reflected on the window object.

It seems like all the properties we passed to the function without the new keyword has been set to the window object. That is because by that time this variable inside the function is referencing to the global or the window object, basically what we have done here is we have polluted the global object. That is a very nasty thing you can do to your JavaScript program. So with the new operator, JavaScript engine sets the this variable to reference the newly created object instance behind the scene, that is why we can see all the properties we passed to the constructor function has been set to the mike. But in the case with calling the constructor function without the new operator, JavaScript engine would interpret this as a regular function call without explicit return statement return undefined. That is why it is very critical to understand how the new operator works in JavaScript.

I hope now you have a good understanding of factory functions, constructor functions, and new keyword in JavaScript. Feel free to ask any questions if you have any. Cheers!!

Versatile Full-stack Developer with 5+ years of experience designing, developing, and managing complex applications and internal frameworks.

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