Skip to main content

Command Palette

Search for a command to run...

What Does the "new" Keyword Do in JavaScript?

Published
16 min read

Introduction

The new keyword is one of the most powerful features in JavaScript. It's used to create new objects from a template called a constructor function. You've probably used it before with built-in objects like new Date() or new Array(), but do you understand what's actually happening behind the scenes? In this blog, we'll explore the new keyword in detail, understand how it creates objects, and learn how it connects objects to their constructors through prototypes.


1. What Does the new Keyword Do?

The new keyword is used to create a new object based on a constructor function. It does several important things automatically.

Basic Concept:

Think of a constructor function as a blueprint for creating objects. Just like a cookie cutter shapes dough into cookies, a constructor function shapes data into objects.

// A constructor function (by convention, starts with capital letter)
function Car(brand, model) {
  this.brand = brand;
  this.model = model;
}

// Without new - just calling the function
Car("Toyota", "Fortuner"); // Returns undefined, creates nothing

// With new - creates a new object
const myCar = new Car("Toyota", "Fortuner");
console.log(myCar); // { brand: "Toyota", model: "Fortuner" }
console.log(myCar.brand); // "Toyota"

Notice the difference? Without new, the function just runs and returns undefined. With new, it creates a brand new object and returns it.

The Four Things new Does:

When you use the new keyword, JavaScript does four things automatically:

  1. Creates a new empty object

  2. Sets up the object's prototype chain

  3. Runs the constructor function with this bound to the new object

  4. Returns the new object (unless the constructor explicitly returns something else)

Let's explore each step in detail.


2. Understanding Constructor Functions

A constructor function is a regular function that's designed to be called with the new keyword. By convention, constructor function names start with a capital letter.

Creating a Simple Constructor:

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

const person1 = new Person("Aman", 25);
const person2 = new Person("Sneha", 23);

console.log(person1); // { name: "Aman", age: 25 }
console.log(person2); // { name: "Sneha", age: 23 }

console.log(person1.name); // "Aman"
console.log(person2.name); // "Sneha"

Each time you call new Person(...), it creates a completely new object with its own properties.

Adding Methods to Constructor:

You can also add methods to the objects created by a constructor:

function Student(name, rollNumber) {
  this.name = name;
  this.rollNumber = rollNumber;
  
  // Method inside constructor
  this.introduce = function() {
    return "Hello, I am " + this.name + ", roll number " + this.rollNumber;
  };
}

const student1 = new Student("Priya", 101);
const student2 = new Student("Rohit", 102);

console.log(student1.introduce()); // Hello, I am Priya, roll number 101
console.log(student2.introduce()); // Hello, I am Rohit, roll number 102

Comparison: Constructor vs Regular Function

// As a constructor (with new)
function Bike(brand) {
  this.brand = brand;
}

const myBike = new Bike("Hero");
console.log(myBike); // { brand: "Hero" }
console.log(myBike instanceof Bike); // true

// As a regular function (without new)
function regularBike(brand) {
  this.brand = brand;
}

const result = regularBike("Hero");
console.log(result); // undefined
console.log(this.brand); // "Hero" (this is global object, not good!)

The new keyword makes all the difference. Without it, this refers to the global object, which is usually not what you want.


3. The Object Creation Process: Step by Step

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

Step 1: A New Empty Object is Created

function Animal(type) {
  // Step 1: JavaScript creates a new empty object
  // const newObject = {};
  
  // Step 2: this now refers to newObject
  this.type = type;
}

const dog = new Animal("Dog");

Before any code in the constructor runs, JavaScript creates an empty object.

Step 2: The Prototype is Set Up (We'll cover this more in depth later)

function Animal(type) {
  // The new object's prototype is set to Animal.prototype
  this.type = type;
}

const dog = new Animal("Dog");
// dog's prototype chain is connected to Animal.prototype

Step 3: The Constructor Function Runs with this Bound to the New Object

function Animal(type, legs) {
  console.log("Constructor called");
  
  // this refers to the newly created object
  this.type = type;
  this.legs = legs;
  this.makeSound = function() {
    return "Some sound";
  };
}

const cat = new Animal("Cat", 4);
console.log(cat.type); // "Cat"
console.log(cat.legs); // 4
console.log(cat.makeSound()); // "Some sound"

All the properties and methods are added to the new object through the this keyword.

Step 4: The New Object is Returned

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

// The new object is automatically returned
const myBook = new Book("The Great Gatsby", "F. Scott Fitzgerald");
console.log(myBook); // { title: "The Great Gatsby", author: "F. Scott Fitzgerald" }

Unless the constructor explicitly returns a different object, the newly created object is returned.

Complete Example Showing All Steps:

function Movie(title, year) {
  console.log("1. Object created");
  console.log("2. this is:", this);
  
  this.title = title;
  this.year = year;
  
  console.log("3. Properties set");
  console.log("4. Object will be returned");
}

console.log("Creating a movie...");
const movie = new Movie("Dangal", 2016);
console.log("5. Object returned:");
console.log(movie);

// Output:
// Creating a movie...
// 1. Object created
// 2. this is: Movie {}
// 3. Properties set
// 4. Object will be returned
// 5. Object returned:
// { title: "Dangal", year: 2016 }

4. Constructor Functions with Properties and Methods

Let's create more realistic constructors that have both properties and methods.

Simple Constructor with Properties:

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

const car1 = new Car("Honda", "City", 2020);
const car2 = new Car("Maruti", "Swift", 2019);

console.log(car1); // { brand: "Honda", model: "City", year: 2020 }
console.log(car2); // { brand: "Maruti", model: "Swift", year: 2019 }

Constructor with Methods:

function BankAccount(accountHolder, initialBalance) {
  this.accountHolder = accountHolder;
  this.balance = initialBalance;
  
  // Method to check balance
  this.checkBalance = function() {
    return "Balance: Rs." + this.balance;
  };
  
  // Method to deposit
  this.deposit = function(amount) {
    this.balance += amount;
    return "Deposited Rs." + amount + ". New balance: Rs." + this.balance;
  };
  
  // Method to withdraw
  this.withdraw = function(amount) {
    if (amount <= this.balance) {
      this.balance -= amount;
      return "Withdrawn Rs." + amount + ". New balance: Rs." + this.balance;
    } else {
      return "Insufficient balance";
    }
  };
}

const myAccount = new BankAccount("Arun Kumar", 5000);
console.log(myAccount.checkBalance()); // Balance: Rs.5000
console.log(myAccount.deposit(2000)); // Deposited Rs.2000. New balance: Rs.7000
console.log(myAccount.withdraw(1500)); // Withdrawn Rs.1500. New balance: Rs.5500

Constructor with Logic:

function Temperature(celsius) {
  this.celsius = celsius;
  
  this.toFahrenheit = function() {
    return (this.celsius * 9/5) + 32;
  };
  
  this.getDescription = function() {
    if (this.celsius < 0) {
      return "Freezing";
    } else if (this.celsius < 15) {
      return "Cold";
    } else if (this.celsius < 25) {
      return "Moderate";
    } else {
      return "Hot";
    }
  };
}

const temp = new Temperature(20);
console.log(temp.toFahrenheit()); // 68
console.log(temp.getDescription()); // Moderate

This is one of the most important concepts related to the new keyword. When you use new, JavaScript automatically sets up a connection between the new object and the constructor's prototype.

Understanding Prototypes:

Every function in JavaScript has a special property called prototype. This prototype is an object that will be shared by all instances created from that constructor.

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

// Add a method to the prototype
Dog.prototype.bark = function() {
  return this.name + " says: Woof! Woof!";
};

const dog1 = new Dog("Buddy");
const dog2 = new Dog("Max");

console.log(dog1.bark()); // "Buddy says: Woof! Woof!"
console.log(dog2.bark()); // "Max says: Woof! Woof!"

Both dog1 and dog2 can access the bark method even though it's not directly on the objects. They access it through the prototype.

Why Use Prototypes?

If you define methods inside the constructor, each object gets its own copy of the method:

function Animal1(type) {
  this.type = type;
  
  // Method defined in constructor
  this.makeSound = function() {
    return "Sound from " + this.type;
  };
}

const animal1 = new Animal1("Lion");
const animal2 = new Animal1("Tiger");

// Each object has its own makeSound function
console.log(animal1.makeSound === animal2.makeSound); // false

This wastes memory because you're creating the same function multiple times.

With prototypes, all objects share the same method:

function Animal2(type) {
  this.type = type;
}

// Method defined on prototype
Animal2.prototype.makeSound = function() {
  return "Sound from " + this.type;
};

const animal1 = new Animal2("Lion");
const animal2 = new Animal2("Tiger");

// All objects share the same makeSound function
console.log(animal1.makeSound === animal2.makeSound); // true
console.log(animal1.makeSound()); // "Sound from Lion"
console.log(animal2.makeSound()); // "Sound from Tiger"

This is much more efficient.

The Prototype Chain:

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

Bird.prototype.fly = function() {
  return this.name + " is flying";
};

Bird.prototype.chirp = function() {
  return this.name + " is chirping";
};

const sparrow = new Bird("Sparrow");

console.log(sparrow.name); // Own property: "Sparrow"
console.log(sparrow.fly()); // From prototype: "Sparrow is flying"
console.log(sparrow.chirp()); // From prototype: "Sparrow is chirping"

JavaScript looks for properties first on the object itself. If not found, it looks on the prototype.

Checking Prototype Connection:

function Teacher(subject) {
  this.subject = subject;
}

const teacher = new Teacher("Math");

// Check if teacher is an instance of Teacher
console.log(teacher instanceof Teacher); // true

// Check if teacher's prototype is Teacher.prototype
console.log(Object.getPrototypeOf(teacher) === Teacher.prototype); // true

// Check the prototype chain
console.log(teacher.constructor); // Teacher function

6. Instances Created from Constructors

An instance is an object created from a constructor function. Each instance is a separate object with its own properties.

Creating Multiple Instances:

function Pizza(size, toppings) {
  this.size = size;
  this.toppings = toppings;
}

const pizza1 = new Pizza("Large", ["Cheese", "Pepperoni"]);
const pizza2 = new Pizza("Medium", ["Vegetables"]);
const pizza3 = new Pizza("Small", ["Cheese"]);

console.log(pizza1); // { size: "Large", toppings: ["Cheese", "Pepperoni"] }
console.log(pizza2); // { size: "Medium", toppings: ["Vegetables"] }
console.log(pizza3); // { size: "Small", toppings: ["Cheese"] }

Each pizza is a separate instance with its own properties.

Instances are Independent:

function Person(name) {
  this.name = name;
  this.friends = [];
}

const person1 = new Person("Raj");
const person2 = new Person("Priya");

person1.friends.push("Ajay");
person1.friends.push("Vijay");

console.log(person1.friends); // ["Ajay", "Vijay"]
console.log(person2.friends); // [] - unaffected

Changing one instance doesn't affect others.

instanceof Operator:

The instanceof operator checks if an object is an instance of a constructor:

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

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

const lion = new Lion("Simba");
const tiger = new Tiger("Shere Khan");

console.log(lion instanceof Lion); // true
console.log(lion instanceof Tiger); // false
console.log(tiger instanceof Tiger); // true
console.log(tiger instanceof Lion); // false

The constructor Property:

Every instance has a constructor property that points back to its constructor function:

function Car(brand) {
  this.brand = brand;
}

const car = new Car("BMW");

console.log(car.constructor); // Car function
console.log(car.constructor === Car); // true
console.log(car.constructor.name); // "Car"

7. Common Constructor Patterns

Pattern 1: Property Initialization

function Rectangle(width, height) {
  this.width = width;
  this.height = height;
  this.area = width * height;
}

const rect = new Rectangle(10, 20);
console.log(rect.area); // 200

Pattern 2: Methods for Calculation

function Circle(radius) {
  this.radius = radius;
  
  this.getArea = function() {
    return Math.PI * this.radius * this.radius;
  };
  
  this.getCircumference = function() {
    return 2 * Math.PI * this.radius;
  };
}

const circle = new Circle(5);
console.log(circle.getArea()); // 78.54
console.log(circle.getCircumference()); // 31.42

Pattern 3: Methods on Prototype (More Efficient)

function Player(name, position) {
  this.name = name;
  this.position = position;
  this.score = 0;
}

Player.prototype.scoreGoal = function() {
  this.score++;
  return this.name + " scored! Total: " + this.score;
};

Player.prototype.getStats = function() {
  return this.name + " (" + this.position + "): " + this.score + " goals";
};

const player1 = new Player("Virat", "Batsman");
const player2 = new Player("Rohit", "Batsman");

console.log(player1.scoreGoal()); // Virat scored! Total: 1
console.log(player1.scoreGoal()); // Virat scored! Total: 2
console.log(player1.getStats()); // Virat (Batsman): 2 goals
console.log(player2.getStats()); // Rohit (Batsman): 0 goals

Pattern 4: Private Properties (Simulated)

function BankAccount(accountHolder, initialBalance) {
  // Private variable (not accessible from outside)
  let balance = initialBalance;
  
  this.accountHolder = accountHolder;
  
  // Public method to access balance
  this.getBalance = function() {
    return balance;
  };
  
  // Public method to deposit
  this.deposit = function(amount) {
    balance += amount;
    return "Deposited Rs." + amount;
  };
  
  // Public method to withdraw
  this.withdraw = function(amount) {
    if (amount <= balance) {
      balance -= amount;
      return "Withdrawn Rs." + amount;
    } else {
      return "Insufficient balance";
    }
  };
}

const account = new BankAccount("Rajesh", 5000);
console.log(account.getBalance()); // 5000
console.log(account.deposit(2000)); // Deposited Rs.2000
console.log(account.getBalance()); // 7000
console.log(account.balance); // undefined - balance is private

8. Prototype Linking Visual Guide

Here's how the prototype chain works:

Instance Object
      |
      ├─ Own Properties: name, age, etc.
      |
      └─ Prototype Link (internal [[Prototype]])
            |
            v
         Constructor.prototype
            |
            ├─ Methods: bark(), eat(), sleep()
            |
            └─ Prototype Link (internal [[Prototype]])
                  |
                  v
               Object.prototype
                  |
                  ├─ Methods: toString(), hasOwnProperty()
                  |
                  └─ Prototype Link (null)

Example Showing the Chain:

function Animal(type) {
  this.type = type;
}

Animal.prototype.speak = function() {
  return "Speaking";
};

const dog = new Animal("Dog");

// Check where properties come from
console.log(dog.type); // Own property
console.log(dog.speak()); // From Animal.prototype
console.log(dog.toString()); // From Object.prototype

// Verify the prototype chain
console.log(Object.getPrototypeOf(dog) === Animal.prototype); // true
console.log(Object.getPrototypeOf(Animal.prototype) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype)); // null (end of chain)

9. Constructor Functions vs Classes

In modern JavaScript, you can achieve the same thing with classes. Classes are syntactic sugar over constructor functions:

Using Constructor Function:

function Teacher(name, subject) {
  this.name = name;
  this.subject = subject;
}

Teacher.prototype.teach = function() {
  return this.name + " is teaching " + this.subject;
};

const teacher = new Teacher("Mr. Sharma", "Mathematics");
console.log(teacher.teach()); // Mr. Sharma is teaching Mathematics

Using Class (Same Functionality):

class Teacher {
  constructor(name, subject) {
    this.name = name;
    this.subject = subject;
  }
  
  teach() {
    return this.name + " is teaching " + this.subject;
  }
}

const teacher = new Teacher("Mr. Sharma", "Mathematics");
console.log(teacher.teach()); // Mr. Sharma is teaching Mathematics

Both approaches work identically. Classes are just a newer, cleaner syntax.


10. Common Mistakes with the new Keyword

Mistake 1: Forgetting the new Keyword

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

const user1 = new User("Arun"); // Correct
console.log(user1); // { name: "Arun" }

const user2 = User("Arun"); // Forgot new
console.log(user2); // undefined
console.log(this.name); // "Arun" - this is global object (bad!)

Solution: Always use new with constructors, or use classes which enforce it.

Mistake 2: Defining Methods in Constructor

// Inefficient - each object gets its own copy of the method
function Dog(name) {
  this.name = name;
  
  this.bark = function() {
    return this.name + " barks";
  };
}

const dog1 = new Dog("Buddy");
const dog2 = new Dog("Max");

console.log(dog1.bark === dog2.bark); // false - different functions!

Solution: Define methods on the prototype

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

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

const dog1 = new Dog("Buddy");
const dog2 = new Dog("Max");

console.log(dog1.bark === dog2.bark); // true - same function

Mistake 3: Not Using Capital Letters

// Bad: Doesn't follow convention
function car(brand) {
  this.brand = brand;
}

const myCar = new car("Honda"); // Works, but confusing

// Good: Follows convention
function Car(brand) {
  this.brand = brand;
}

const myCar = new Car("Honda");

By convention, constructor functions should start with a capital letter to signal that they should be used with new.

Mistake 4: Returning Objects from Constructor

function WrongConstructor(name) {
  this.name = name;
  
  // Returning an object will replace the instance
  return { different: "object" };
}

const obj = new WrongConstructor("Test");
console.log(obj); // { different: "object" } - not what we expected

If a constructor returns an object, that object is returned instead of the created instance. Usually, you don't want this.


11. Real-World Example: Building a Library System

Let's create a complete example using constructors:

// Book constructor
function Book(title, author, isbn, year) {
  this.title = title;
  this.author = author;
  this.isbn = isbn;
  this.year = year;
  this.isAvailable = true;
}

Book.prototype.getInfo = function() {
  return this.title + " by " + this.author + " (" + this.year + ")";
};

Book.prototype.borrowBook = function() {
  if (this.isAvailable) {
    this.isAvailable = false;
    return "Book borrowed: " + this.title;
  } else {
    return this.title + " is not available";
  }
};

Book.prototype.returnBook = function() {
  this.isAvailable = true;
  return "Book returned: " + this.title;
};

// Member constructor
function Member(name, memberId) {
  this.name = name;
  this.memberId = memberId;
  this.borrowedBooks = [];
}

Member.prototype.borrowBook = function(book) {
  const result = book.borrowBook();
  if (book.isAvailable === false) {
    this.borrowedBooks.push(book.title);
  }
  return this.name + " - " + result;
};

Member.prototype.returnBook = function(book) {
  const index = this.borrowedBooks.indexOf(book.title);
  if (index > -1) {
    this.borrowedBooks.splice(index, 1);
    book.returnBook();
    return this.name + " returned " + book.title;
  }
  return "This book was not borrowed by " + this.name;
};

// Creating books
const book1 = new Book("The Great Gatsby", "F. Scott Fitzgerald", "978-0-7432-7356-5", 1925);
const book2 = new Book("To Kill a Mockingbird", "Harper Lee", "978-0-06-112008-4", 1960);

// Creating members
const member1 = new Member("Rajesh Kumar", "M001");
const member2 = new Member("Priya Singh", "M002");

// Using the library system
console.log(book1.getInfo()); // The Great Gatsby by F. Scott Fitzgerald (1925)
console.log(member1.borrowBook(book1)); // Rajesh Kumar - Book borrowed: The Great Gatsby
console.log(book1.isAvailable); // false
console.log(member2.borrowBook(book1)); // Priya Singh - The Great Gatsby is not available
console.log(member1.returnBook(book1)); // Rajesh Kumar returned The Great Gatsby
console.log(book1.isAvailable); // true
console.log(member2.borrowBook(book1)); // Priya Singh - Book borrowed: The Great Gatsby

12. Constructor Creation Flow Diagram

Here's a visual representation of what happens when you use new:

Code: const car = new Car("BMW");
       |
       v
Step 1: Create empty object
       const obj = {};
       |
       v
Step 2: Set prototype
       obj.__proto__ = Car.prototype;
       |
       v
Step 3: Call constructor with this = obj
       Car.call(obj, "BMW");
       |
       ├─ this.brand = "BMW"
       |
       v
Step 4: Return the object
       return obj;
       |
       v
Result: car = { brand: "BMW" }
        car.__proto__ = Car.prototype

Conclusion

The new keyword is a fundamental part of JavaScript that enables object-oriented programming. Here's what we've learned:

  1. new creates a new object and runs the constructor function with this bound to that object

  2. Constructor functions are templates for creating objects with shared properties and methods

  3. The new keyword automatically sets up the prototype chain, linking instances to the constructor's prototype

  4. Methods defined on the prototype are shared by all instances, making code more efficient

  5. Each instance is independent with its own properties

  6. Understanding new is essential for working with JavaScript objects

The new keyword transforms a simple function into a powerful object factory. With this knowledge, you can create well-organized, efficient code that takes full advantage of JavaScript's object-oriented capabilities. Start using constructors in your projects, and you'll find your code becomes more structured and maintainable.