Understanding Constructor Functions in JavaScript for Object Creation

Constructor Execution Steps

When a constructor function is invoked with the new keyword, the following steps occur:

  1. A new empty object is created in memory.
  2. The [[Prototype]] of that new object is linked to the constructor's prototype property.
  3. The this binding inside the constructor is set to the newly created object.
  4. The constructor's code executes, adding properties and methods to this.
  5. If the constructor returns a non-primitive value (an object), that value is returned instead of the newly created object. Otherwise, the new object is returned.

Every instance created by a constructor has a constructor property that points back to the constructor function:

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function() {
        console.log(this.name);
    };
}

let person1 = new Person("Nicholas", 29, "Software Engineer");
let person2 = new Person("Greg", 27, "Doctor");

console.log(person1.constructor == Person); // true
console.log(person2.constructor == Person); // true

While constructor can identify the type, the instanceof operator is generally more reliable for type checking:

console.log(person1 instanceof Person); // true
console.log(person1 instanceof Object); // true
console.log(person2 instanceof Person); // true
console.log(person2 instanceof Object); // true

Custom constructors allow instances to be identified as a specific type, which is a key improvement over the factory pattern. All custom objects inherit from Object by default.

Funcsion Expressions as Constructors

Constructors can be defined using function expressions as well as declarations:

let Person = function(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function() {
        console.log(this.name);
    };
};

let person1 = new Person("Nicholas", 29, "Software Engineer");
console.log(person1 instanceof Person); // true
console.log(person1 instanceof Object); // true

Optional Parentheses

If no arguments are required, the parentheses after the constructor name are optional when using new:

function Person() {
    this.name = "Jake";
    this.sayName = function() {
        console.log(this.name);
    };
}

let person1 = new Person();
let person2 = new Person;

person1.sayName(); // Jake
person2.sayName(); // Jake

Constructors Are Regular Functions

The only difference between a constructor and a regular function is the invocation context. Any function can act as a constructor if called with new, or as a regular function if called without it:

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function() {
        console.log(this.name);
    };
}

// Called as constructor
let person = new Person("Nicholas", 29, "Software Engineer");
person.sayName(); // "Nicholas"

// Called as regular function (adds properties to global object in non-strict mode)
Person("Greg", 27, "Doctor");
window.sayName(); // "Greg"

// Called with explicit scope via call()
let o = {};
Person.call(o, "Kristen", 25, "Nurse");
o.sayName(); // "Kristen"

When a function is called without an explicit this context (no object method, no call/apply), this defaults to the global object (window in browsers). Using call() or apply() allows you to set this to any object, effectively copying the constructor's properties to that object.

The Method Duplication Problem

A significant drawback of constructors is that methods are recreated for every instance. Each instance gets its own copy of the functon, which is wasteful:

function Person(name) {
    this.name = name;
    this.sayName = function() {
        console.log(this.name);
    };
}

// Behind the scenes, this is equivalent to:
// this.sayName = new Function("console.log(this.name)");

let person1 = new Person("Alice");
let person2 = new Person("Bob");

console.log(person1.sayName === person2.sayName); // false

Each sayName function is a distinct Function instance, consuming extra memory. This issue is addressed by sharing methods through the prototype chain, which is covered in subsequent chapters on prtootypal inheritance.

Tags: javascript constructor new operator Object Creation this binding

Posted on Mon, 20 Jul 2026 17:18:30 +0000 by thompsonsco