Skip to main content

Command Palette

Search for a command to run...

Demystifying ' new ' keyword in JavaScript

How Constructor Functions & Prototypes Work Under the Hood

Updated
•4 min read•View as Markdown
Demystifying ' new ' keyword in JavaScript
S
I like to make complex technical topics easy.

JavaScript's new keyword often feels like magic, especially if you come from class-based Object-Oriented languages like Java or C++. However, behind the scenes, new simply automates a very specific set of object creation steps and prototype linkages.

In this guide, we’ll break down what new actually does, how constructor functions work, and how JavaScript connects objects through its prototype chain.


What is a Constructor Function?

A constructor function in JavaScript is a regular function used to construct and initialize objects, or we can say it is a 'blueprint' that is used to create similar objects.

By convention, constructor function names start with a capital letter to distinguish them from standard functions.

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

If you call Person('Alice', 25) without new, this will refer to the global object (window in browsers) or undefined in strict mode.

Using new changes everything!


What Does the new Keyword Actually Do?

When you execute new Person('Alice', 25), JavaScript performs 4 step-by-step actions behind the scenes:

  1. Creates a brand new empty object: {}

  2. Links the Prototype: Sets the internal [[Prototype]] (__proto__) of the new object to match the constructor’s .prototype property.

  3. Binds this & Executes: Runs the constructor function with this bound to the newly created object.

  4. Returns the Object: Returns the new object automatically, unless the constructor function explicitly returns its own non-primitive object.


Visualizing Object Creation & Prototype Linking

Here is the step-by-step mental model for how a constructor produces an instance and connects it to the prototype chain:

Constructor Function: Person()
   │
   ├──> Person.prototype ───► { sayHello: function() }
   │                                  ▲
   │ (calls: new Person('Alice'))     │ [[Prototype]] Link
   ▼                                  │
Instance Created: alice ──────────────┘
{ name: 'Alice', age: 25 }

Instead of attaching methods inside the constructor function (which creates duplicate function instances in memory for every object), you attach methods to the constructor’s .prototype.

// 1. Constructor Function
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 2. Add shared method to prototype
Person.prototype.sayHello = function() {
  console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old.`);
};

// 3. Create instances using `new`
const alice = new Person('Alice', 25);
const bob = new Person('Bob', 30);

alice.sayHello(); // Output: Hi, I'm Alice and I'm 25 years old.
bob.sayHello();   // Output: Hi, I'm Bob and I'm 30 years old.

Because new automatically sets up the internal prototype link:

console.log(Object.getPrototypeOf(alice) === Person.prototype); // true
console.log(alice.sayHello === bob.sayHello);                   // true (shares memory!)

Instances Created from Constructors

Objects created with new are instances of that constructor function. You can verify instance relationships using the instanceof operator or checking the .constructor property:

console.log(alice instanceof Person); // true
console.log(alice.constructor === Person); // true

Polyfilling new: Building Your Own customNew

The best way to truly understand new is to write a function that replicates its exact logic:

function customNew(Constructor, ...args) {
  // Step 1: Create a new plain object
  const obj = {};

  // Step 2: Link [[Prototype]] to Constructor's prototype
  Object.setPrototypeOf(obj, Constructor.prototype);

  // Step 3: Call Constructor with `this` set to our new object
  const result = Constructor.apply(obj, args);

  // Step 4: Return object or result if it returned an object explicitly
  return (typeof result === 'object' && result !== null) ? result : obj;
}

// Testing customNew
const charlie = customNew(Person, 'Charlie', 22);
charlie.sayHello(); // Output: Hi, I'm Charlie and I'm 22 years old.

Summary

  • The new keyword automates object creation, this binding, prototype linking, and returning the newly instantiated object.

  • Methods defined on Constructor.prototype are shared among all instances, saving memory.

  • Even modern ES6 JavaScript class syntax is mostly syntactical sugar over this exact prototype-based mechanism!