Understanding the new Keyword in JavaScript

Today let's start with an example.
function Student(name, standard, age) {
this.name = name;
this.standard = standard;
this.age = age;
}
Here we have a blueprint for creating student objects. This blueprint is known as a constructor function.
But how do we create multiple instances?
If we do this:
const st1 = Student("Ram", 12, 16);
const st2 = Student("Shyam", 10, 14);
console.log(st1);
console.log(st2);
Output:
undefined
undefined
Why?
Because the function doesn't return anything.
In JavaScript, if a function doesn't explicitly return a value, it returns undefined.
Therefore:
const st1 = Student("Ram", 12, 16);
assigns undefined to st1.
Factory Function Approach
Let's manually create and return an object.
function student(name, standard, age) {
const student = {};
student.name = name;
student.standard = standard;
student.age = age;
return student;
}
const st1 = student("Ram", 12, 16);
const st2 = student("Shyam", 10, 14);
console.log(st1);
console.log(st2);
Output:
{ name: 'Ram', standard: 12, age: 16 }
{ name: 'Shyam', standard: 10, age: 14 }
This pattern is known as a Factory Function because the function manufactures and returns objects.
Why Do We Need new Then?
Creating objects from a blueprint is extremely common, and most of the time a blueprint contains methods as well.
With factory functions, we have to manually create and return both the object and its methods:
function createStudent(name, standard, age) {
return {
name,
standard,
age,
intro() {
console.log(`I am ${name}`);
}
};
}
Every time createStudent() is called, a new copy of the intro() method is created.
const st1 = createStudent("Ram", 12, 16);
const st2 = createStudent("Shyam", 10, 14);
console.log(st1.intro === st2.intro); // false
Since each instance gets its own copy of the method, memory usage increases as more objects are created.
That's why, rather than manually creating objects and methods every time, JavaScript provides the new keyword along with the prototype system.
function Student(name, standard, age) {
this.name = name;
this.standard = standard;
this.age = age;
}
const st1 = new Student("Ram", 12, 16);
const st2 = new Student("Shyam", 10, 14);
console.log(st1);
console.log(st2);
Output:
Student { name: 'Ram', standard: 12, age: 16 }
Student { name: 'Shyam', standard: 10, age: 14 }
The result looks similar to the factory function approach.
The difference lies in what JavaScript does internally. When new creates an object, it automatically links that object to Student.prototype. This allows all instances to share the same methods through the prototype chain instead of storing separate copies in every object, will see more in later section.
What Happens Internally When We Use new?
When JavaScript sees:
const st1 = new Student("Ram", 12, 16);
it roughly performs four steps.
Step 1: Create an Empty Object
const obj = {};
Step 2: Link the Object to Student.prototype
obj.__proto__ = Student.prototype;
This establishes the prototype chain.
Because of this linkage:
st1 instanceof Student
returns:
true
Without this step, JavaScript would not recognize the object as an instance of Student.
If you're new to prototypes, just remember:
Every constructor function has a
prototypeobject, and objects created usingneware linked to that prototype.
This is a reason where new keyword overshines factory function approach.
Rather than
function createStudent(name, standard, age) {
return {
name,
standard,
age,
intro() {
console.log(`I am ${name}`);
}
};
}
Since new do this obj.__proto__ = student.prototype
function Student(name, standard, age) {
this.name = name;
this.standard = standard;
this.age = age;
}
Student.prototype.intro = function () {
console.log(`I am ${this.name}`);
};
This way we add methods, to be shared to instances, we add them in protoype of constructor.
All instances can access these methods without having their own copies, because they inherit them from the constructor's prototype.
Step 3: Call the Constructor Function
JavaScript executes:
Student.call(obj, "Ram", 12, 16);
which means this now points to obj.
function Student(name, standard, age) {
this.name = name;
this.standard = standard;
this.age = age;
}
effectively becomes:
obj.name = "Ram";
obj.standard = 12;
obj.age = 16;
Step 4: Return the Object
Finally, JavaScript returns the object.
return obj;
So the entire process can be visualized as:
function pseudoNew(Student, ...args) {
const obj = {};
obj.__proto__ = Student.prototype;
Student.call(obj, ...args);
return obj;
}
Therefore:
const st1 = new Student("Ram", 12, 16);
is conceptually similar to:
const st1 = pseudoNew(Student, "Ram", 12, 16);
Summary
When we use new, JavaScript automatically:
Creates an empty object.
Links it to the constructor's prototype.
Calls the constructor with
thispointing to that object.Returns the object.
This is why constructor functions and the new keyword became the traditional way of creating object instances in JavaScript. Even though class syntax was introduced in ES6, it is nothing but syntactic sugar and internally uses new only.
