Skip to main content

Command Palette

Search for a command to run...

The new Keyword in JavaScript

Updated
•4 min read•View as Markdown

Imagine you are building a simple web game. You need to create a horde of enemies. You could manually create an object for every single one:

const goblin1 = { name: 'Goblin', hp: 50, level: 1 };
const goblin2 = { name: 'Goblin', hp: 50, level: 1 };
// ... 98 more times

This is obviously a maintenance nightmare. Instead of building every object by hand, what you really need is an "enemy factory"—a blueprint that can stamp out new, independent enemy objects on demand.

In JavaScript, we achieve this using Constructor Functions paired with the incredibly powerful new keyword. But what exactly happens when you type new? Let's peel back the layers and look at the step-by-step object creation process.

The Blueprint: Constructor Functions

Before we can use new, we need a constructor. A constructor function is, technically speaking, just a completely normal JavaScript function.

However, by convention, we capitalize the first letter of its name to signal to other developers: "Hey, do not call this function normally! It is meant to be used with new."

function Player(username, characterClass) {
  this.name = username;
  this.role = characterClass;
  this.level = 1;
}

If you just run Player('Alex', 'Mage') without the new keyword, it won't work the way you expect. In a browser, this would accidentally point to the global window object, causing bugs.

To make this blueprint actually build something, we must invoke it with new.

The 4-Step Magic of new

When you write const player1 = new Player('Alex', 'Mage');, JavaScript intercepts that call and performs four distinct steps behind the scenes.

Step 1: An Empty Object is Born

The moment new is executed, JavaScript immediately creates a brand-new, completely empty object in memory: {}.

This is the secret sauce of JavaScript's object-oriented design. JavaScript takes that newly created empty object and links its hidden internal [[Prototype]] to the constructor function's prototype property. (We will explore why this is so important in just a moment).

Step 3: this is Bound to the New Object

JavaScript now calls your Player function, but it forces the this keyword to point directly at the brand-new object created in Step 1.

So, when the function runs:

  • this.name = 'Alex' adds a name property to the new object.

  • this.role = 'Mage' adds a role property.

  • this.level = 1 adds a level property.

Step 4: The Object is Returned

Finally, unless your constructor function explicitly returns a different custom object, the new keyword automatically returns that freshly populated object.

You now have a fully formed instance!

const player1 = new Player('Alex', 'Mage');
const player2 = new Player('Sam', 'Warrior');

console.log(player1.name); // Output: Alex
console.log(player2.role); // Output: Warrior

Why Step 2 Matters: Prototypes and Memory

You might be wondering: If I want my players to be able to attack, should I add an attack function inside the constructor?

function Player(username) {
  this.name = username;
  // This works, but it's a bad idea:
  this.attack = function() { console.log("Swing sword!"); } 
}

While that works, it is highly inefficient. If you create 1,000 players using new, JavaScript will create 1,000 separate, identical copies of the attack function in memory.

This is where Step 2 (the prototype link) saves the day. Instead of putting methods inside the constructor, we attach them to the constructor's prototype:

function Player(username) {
  this.name = username;
}

// We add the method to the prototype once
Player.prototype.attack = function() {
  console.log(`${this.name} swings their weapon!`);
};

const player1 = new Player('Alex');
player1.attack(); // Output: Alex swings their weapon!

Because new automatically linked player1 to Player.prototype, when you call player1.attack(), JavaScript looks at player1, doesn't see an attack function, follows the link to the prototype, finds the function there, and executes it perfectly.

You now have 1,000 players sharing a single attack function in memory.