Skip to main content

Command Palette

Search for a command to run...

The new Keyword in JavaScript

Updated
14 min read
The new Keyword in JavaScript
H
CS undergrad | Tech enthusiast | Focusing on Web Dev • DSA • ML | Building skills for real-world impact

The new keyword is one of the most misunderstood parts of JavaScript. Most developers use it without really understanding what it does. But once you understand it, object creation becomes crystal clear.

This is about what new actually does, how constructor functions work, and how objects are created in JavaScript.


What Does new Do?

The new keyword creates a new object and links it to a constructor function. That's it. But there's a specific process that happens behind the scenes.

The new Keyword Does Four Things

When you write:

const person = new Person("John");

JavaScript does this:

1. Create a brand new empty object
2. Set the object's prototype to the constructor's prototype
3. Call the constructor function with 'this' pointing to the new object
4. Return the new object (unless constructor returns something else)

Let's break it down step by step.


Constructor Functions

A constructor function is a regular function designed to be called with the new keyword. It initializes properties on a new object.

Simple Constructor

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

const john = new Person("John");
console.log(john.name); // "John"
console.log(john.age);  // 0

When you call new Person("John"):

  1. A new empty object is created: {}
  2. this inside Person() refers to this new object
  3. this.name = "John" adds a property to the object
  4. this.age = 0 adds another property
  5. The object is returned

Multiple Properties

function Car(brand, model, year) {
  this.brand = brand;
  this.model = model;
  this.year = year;
  this.age = 2026 - year;
}

const myCar = new Car("Toyota", "Camry", 2020);
console.log(myCar.brand); // "Toyota"
console.log(myCar.model); // "Camry"
console.log(myCar.age);   // 6

The constructor adds multiple properties to the new object.

Constructor with Methods

function Dog(name) {
  this.name = name;
  
  // Add a method
  this.bark = function() {
    console.log(this.name + " says woof!");
  };
}

const dog = new Dog("Rex");
dog.bark(); // "Rex says woof!"

The constructor can add methods too, though there's a better way (prototypes).

Without new - It Breaks

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

// WRONG - calling without 'new'
const john = Person("John");
console.log(john); // undefined
console.log(this.name); // "John" - added to global object (bad!)

Without new, this doesn't point to a new object. It points to the global object. This pollutes the global scope. Always use new with constructors.


Object Creation Process Step by Step

Let's trace exactly what happens when you use the new keyword.

Step 1: Create a New Empty Object

const person = new Person("John");

Step 1: Create an empty object
{}

JavaScript creates a brand new empty object.

Step 2: Link the object to Person.prototype
{}.__proto__ = Person.prototype

The new object's internal [[Prototype]] is set to the constructor's prototype property. This creates the prototype chain.

Step 3: Call Constructor with this = New Object

Step 3: Call Person() with this = the new object
Person.call({}, "John")

Inside Person():
this.name = "John"  → {} becomes { name: "John" }
this.age = 0        → {} becomes { name: "John", age: 0 }

The constructor function runs with this pointing to the new object. Any assignments to this update the new object.

Step 4: Return the Object

Step 4: Return the new object
const person = { name: "John", age: 0 }

The new operator returns the object (unless the constructor explicitly returns something else).

Complete Process Visualization

You write:
    const person = new Person("John");
            ↓
JavaScript does:
    1. Create empty object: {}
    2. Set __proto__: {}.__proto__ = Person.prototype
    3. Call constructor: Person.call({}, "John")
       Inside constructor: this.name = "John"
    4. Return: { name: "John", age: 0 }
            ↓
Result:
    person = { name: "John", age: 0 }

Constructor Functions vs Regular Functions

The only difference between a constructor and a regular function is how it's called.

Regular Function

function greet(name) {
  console.log("Hello, " + name);
}

greet("John"); // Regular call
// Output: Hello, John

No new keyword. this is undefined (in strict mode) or the global object.

Constructor Function

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

const john = new Person("John"); // Constructor call
// person = { name: "John" }

Called with new. this refers to the new object.

Same Function, Different Calls

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

// As a regular function
Person("John");
// Output: Window (global object)

// As a constructor
const john = new Person("John");
// Output: Person { name: "John" }

The function is the same. The call context is different.

Convention: Capitalize Constructor Names

By convention, constructor function names start with a capital letter:

function Person(name) { }      // Constructor (capital P)
function greet(name) { }       // Regular function (lowercase g)

This signals to other developers: "This function is meant to be called with new."


Creating Multiple Instances

A constructor creates objects of the same type. Each call to new creates a new instance.

Multiple Instances from One Constructor

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

const john = new Person("John", 30);
const jane = new Person("Jane", 28);
const bob = new Person("Bob", 35);

console.log(john); // { name: "John", age: 30 }
console.log(jane); // { name: "Jane", age: 28 }
console.log(bob);  // { name: "Bob", age: 35 }

Three separate objects, all created from the same constructor.

Each Instance Is Independent

john.age = 31;
console.log(john.age); // 31
console.log(jane.age); // 28 (unchanged)

Changing one instance doesn't affect the others.

Checking Instance Type

console.log(john instanceof Person); // true
console.log(john instanceof Car);    // false

The instanceof operator checks if an object was created by a constructor.


Prototypes and the new Keyword

The new keyword doesn't just create an object. It also links the object to the constructor's prototype.

Understanding prototype

Every function has a prototype property:

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

console.log(Person.prototype); // { constructor: Person }

This prototype is an object that will be shared by all instances.

Adding Methods to Prototype

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

// Add a method to the prototype
Person.prototype.greet = function() {
  console.log("Hello, I'm " + this.name);
};

const john = new Person("John");
john.greet(); // "Hello, I'm John"

All instances created with new Person() have access to greet().

Why Use Prototype?

If you add methods in the constructor:

function Person(name) {
  this.name = name;
  
  this.greet = function() {  // Method added to each instance
    console.log("Hello, I'm " + this.name);
  };
}

const john = new Person("John");
const jane = new Person("Jane");

// Each has its own copy of greet()
// Memory inefficient!

Each instance gets its own copy of the method. Wasteful.

With prototypes:

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

Person.prototype.greet = function() {
  console.log("Hello, I'm " + this.name);
};

const john = new Person("John");
const jane = new Person("Jane");

// Both share the same greet() method
// Memory efficient!

All instances share the same method. Much better.

The Prototype Chain

When you call a method on an instance:

john.greet();

JavaScript looks for greet in this order:

1. Look in john object itself? No.
2. Look in john.__proto__ (which is Person.prototype)? Yes!
3. Call it from there.

This lookup chain is the prototype chain.

When you use new, the created object's [[Prototype]] is set to the constructor's prototype:

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

const john = new Person("John");

// john's prototype is Person.prototype
Object.getPrototypeOf(john) === Person.prototype; // true

This link is created by the new keyword.


The new Keyword Step-by-Step Example

Let's trace a complete example:

Code

function Dog(name, breed) {
  this.name = name;
  this.breed = breed;
}

Dog.prototype.bark = function() {
  console.log(this.name + " barks!");
};

const myDog = new Dog("Rex", "Labrador");
myDog.bark();

Step-by-Step Execution

Step 1: new Dog("Rex", "Labrador") is called

Step 2: Create empty object
myDog = {}

Step 3: Set prototype link
myDog.__proto__ = Dog.prototype

Now myDog can access properties from Dog.prototype

Step 4: Call constructor with this = myDog
In Dog constructor:
  this.name = "Rex"   → myDog = { name: "Rex" }
  this.breed = "Labrador" → myDog = { name: "Rex", breed: "Labrador" }

Step 5: Return myDog
myDog = { name: "Rex", breed: "Labrador", [[Prototype]]: Dog.prototype }

Step 6: Call myDog.bark()
JavaScript looks for bark():
  1. Is bark in myDog? No.
  2. Is bark in myDog.__proto__ (Dog.prototype)? Yes!
  3. Call Dog.prototype.bark() with this = myDog

Output: "Rex barks!"

What If Constructor Returns Something?

Normally, constructors don't return anything (or return undefined). But if they do:

Returning an Object

function Person(name) {
  this.name = name;
  
  return { custom: "object" }; // Return an object
}

const john = new Person("John");
console.log(john); // { custom: "object" }
console.log(john.name); // undefined

If the constructor returns an object, that object is returned instead. The this object is thrown away.

Returning a Primitive

function Person(name) {
  this.name = name;
  
  return "hello"; // Return a primitive
}

const john = new Person("John");
console.log(john); // { name: "John" }
console.log(john.name); // "John"

If the constructor returns a primitive (string, number, etc.), it's ignored. The this object is returned.

Best Practice

Constructors should not return anything:

function Person(name) {
  this.name = name;
  // No return statement
}

const john = new Person("John");
console.log(john); // { name: "John" }

Let the new keyword do its job automatically.


Practical Examples

Example 1: User Constructor

function User(email, password) {
  this.email = email;
  this.password = password;
  this.createdAt = new Date();
}

User.prototype.isValidEmail = function() {
  return this.email.includes("@");
};

const user1 = new User("john@example.com", "secret");
const user2 = new User("jane@example.com", "password");

console.log(user1.isValidEmail()); // true
console.log(user2.email); // "jane@example.com"

Example 2: Product Constructor

function Product(name, price, stock) {
  this.name = name;
  this.price = price;
  this.stock = stock;
}

Product.prototype.inStock = function() {
  return this.stock > 0;
};

Product.prototype.buy = function(quantity) {
  if (quantity > this.stock) {
    console.log("Not enough stock!");
    return false;
  }
  this.stock -= quantity;
  return true;
};

const laptop = new Product("Laptop", 1000, 5);
console.log(laptop.inStock()); // true
laptop.buy(2);
console.log(laptop.stock); // 3

Example 3: Counter Constructor

function Counter(initialValue) {
  this.value = initialValue || 0;
}

Counter.prototype.increment = function() {
  this.value++;
};

Counter.prototype.decrement = function() {
  this.value--;
};

Counter.prototype.getValue = function() {
  return this.value;
};

const counter = new Counter(0);
counter.increment();
counter.increment();
console.log(counter.getValue()); // 2

Example 4: Bank Account Constructor

function BankAccount(owner, balance) {
  this.owner = owner;
  this.balance = balance;
  this.transactions = [];
}

BankAccount.prototype.deposit = function(amount) {
  this.balance += amount;
  this.transactions.push({ type: "deposit", amount });
};

BankAccount.prototype.withdraw = function(amount) {
  if (amount > this.balance) {
    console.log("Insufficient funds");
    return false;
  }
  this.balance -= amount;
  this.transactions.push({ type: "withdraw", amount });
  return true;
};

BankAccount.prototype.getBalance = function() {
  return this.balance;
};

const account = new BankAccount("John", 1000);
account.deposit(500);
account.withdraw(200);
console.log(account.getBalance()); // 1300
console.log(account.transactions); // [{ type: "deposit", amount: 500 }, ...]

new Keyword Flow Diagram

Constructor function defined:
    function Person(name) {
      this.name = name;
    }
            ↓
new Person("John") is called
            ↓
1. Create empty object
    {}
            ↓
2. Link to prototype
    {}.__proto__ = Person.prototype
            ↓
3. Run constructor with this = {}
    this.name = "John"
    {} becomes { name: "John" }
            ↓
4. Return the object
    { name: "John", [[Prototype]]: Person.prototype }
            ↓
Result assigned to variable
    const person = { name: "John" }
            ↓
Instance created and ready to use
    person.name → "John"

Common Mistakes

Mistake 1: Forgetting new with a Constructor

// WRONG
function Person(name) {
  this.name = name;
}

const john = Person("John"); // Forgot 'new'
console.log(john); // undefined
console.log(this.name); // "John" (polluted global!)

// RIGHT
const john = new Person("John");
console.log(john); // { name: "John" }

Mistake 2: Adding Methods to Each Instance

// WRONG - method copied to each instance
function Person(name) {
  this.name = name;
  this.greet = function() {
    console.log("Hello!");
  };
}

// RIGHT - method shared via prototype
function Person(name) {
  this.name = name;
}

Person.prototype.greet = function() {
  console.log("Hello!");
};

Mistake 3: Confusing Constructor Function with Regular Function

// WRONG - treating regular function as constructor
function greet(name) {
  console.log("Hello, " + name);
}

const greeting = new greet("John");
// Creates an object but doesn't do what you want

// RIGHT - call it normally
greet("John");

Mistake 4: Returning from Constructor Incorrectly

// WRONG - return breaks the pattern
function Person(name) {
  this.name = name;
  return this; // Don't do this, let 'new' handle it
}

// RIGHT - don't return anything
function Person(name) {
  this.name = name;
}

Mistake 5: Not Understanding this in Methods

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

Person.prototype.getName = function() {
  return this.name; // 'this' refers to the instance
};

const john = new Person("John");
const getName = john.getName;

getName(); // undefined - 'this' is not john anymore!

// Use bind to fix
const getName = john.getName.bind(john);
getName(); // "John"

Practice Assignment

1. Create a simple constructor:

function Book(title, author, pages) {
  // Add properties for title, author, and pages
}

const myBook = new Book("1984", "George Orwell", 328);
console.log(myBook.title); // "1984"

2. Add methods to the prototype:

function Book(title, author, pages) {
  this.title = title;
  this.author = author;
  this.pages = pages;
}

// Add a method to get book info
Book.prototype.getInfo = function() {
  // Return a string with book information
};

const book = new Book("1984", "Orwell", 328);
console.log(book.getInfo());

3. Create multiple instances:

// Create three books using the Book constructor
const book1 = new Book("1984", "Orwell", 328);
const book2 = new Book("To Kill a Mockingbird", "Lee", 281);
const book3 = new Book("The Great Gatsby", "Fitzgerald", 180);

// Check they are separate instances
console.log(book1 === book2); // false

4. Use instanceof:

const book = new Book("1984", "Orwell", 328);
console.log(book instanceof Book); // true
console.log(book instanceof Person); // false (if Person exists)

5. Understand the prototype chain:

const book = new Book("1984", "Orwell", 328);

// Check what happens when you look up a property
console.log(book.title); // Found in book itself
console.log(book.getInfo()); // Found in Book.prototype

Modern Alternative: Classes

Modern JavaScript (ES6+) has a class syntax that is cleaner than constructor functions:

Constructor Function (Old Way)

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

Person.prototype.greet = function() {
  console.log("Hello, " + this.name);
};

const john = new Person("John");

Class Syntax (New Way)

class Person {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    console.log("Hello, " + this.name);
  }
}

const john = new Person("John");

Under the hood, classes use the same new keyword and prototype system. Classes are just syntactic sugar over constructor functions.

Still Uses new

const john = new Person("John"); // Still need 'new'

Whether you use constructor functions or classes, the new keyword works the same way.


Quick Recap

  • The new keyword creates objects from constructor functions.

  • What new does:

    1. Creates an empty object
    2. Links it to the constructor's prototype
    3. Calls the constructor with this = the new object
    4. Returns the new object
  • Constructor functions are regular functions meant to be called with new.

    • By convention, they start with a capital letter.
    • They use this to add properties.
  • Each call to new creates a new instance - a separate object.

  • Prototypes allow you to share methods across all instances efficiently.

  • The new keyword creates the prototype link - instances inherit from Constructor.prototype.

  • Methods should go on the prototype, not in the constructor.

    • Prototype methods are shared (memory efficient)
    • Constructor properties are instance-specific
  • Without new, this doesn't work correctly - always use new with constructors.

  • Classes are modern syntax for the same old constructor/prototype pattern.

  • Check instance type with instanceof.

Understand the new keyword and object creation becomes intuitive. You'll write better constructors and understand JavaScript's prototype system deeply.

Happy coding! 🚀


If you enjoyed this article, check out my other blogs on this profile. 🔗 Connect with me: LinkedIn | GitHub | X (Twitter)