The New Keyword
What Actually Happens When You Write new Person()

You see new everywhere. new Date(). new Map(). new Promise(). You write it, it works, and you move on. But at some point you start wondering what it actually does. Calling a function with new in front behaves nothing like calling a function without it, and that gap is worth understanding.
Here is the short version: new runs a function in a special mode where that function builds and returns an object. The function is called a constructor. The object it builds is called an instance. That is the whole idea. The rest is just details about how it works.
A constructor is not a special kind of function. It is a regular function that you call with new. The convention is to capitalize the first letter so people know it is meant to be called that way, but JavaScript does not enforce this.
A Constructor Function
Before classes came along in ES6, this is how you made objects that shared a structure. You wrote a plain function, used this inside it, and called it with new. It still works exactly the same way today.
// Capital P signals: call this with new
function Person(name, age) {
this.name = name;
this.age = age;
}
const priya = new Person("Priya", 28);
const rohan = new Person("Rohan", 34);
console.log(priya.name); // "Priya"
console.log(rohan.age); // 34
Each call to new Person() produces a separate object. Priya's name and Rohan's name live on different objects. Changing one does not touch the other. That sounds obvious, but it is worth saying because it is the point.
What new Does
When JavaScript sees new Person("Priya", 28), it does four things in order. You never see any of this happen, but it all runs before your function body even starts.
A blank object is created
JavaScript makes a fresh, empty object. Nothing in it yet. This is what will eventually come back from the call.
**
The prototype is linked**
That blank object gets its internal [[Prototype]] set to Person.prototype. This is how instances share methods without each one getting its own copy. More on this in a moment.
The function runs with this = that object
The constructor body runs, and every time you write this.something, you are writing onto that blank object from step 1.
The object is returned
Unless your constructor explicitly returns a different object, JavaScript returns the one it built in step 1. This is automatic. You do not write return this.
Where Methods Go: The Prototype
Here is something that trips people up early on. If you put a method inside the constructor body using this.greet = function() {...}, every single instance gets its own copy of that function. One hundred Person objects means one hundred separate greet functions sitting in memory, all doing the same thing.
The fix is to put shared methods on Person.prototype instead. Every instance automatically has access to it through the prototype chain, but only one copy exists.
// method in wrong places
function Person(name) {
this.name = name;
// Bad: every new Person() gets its own copy of this function
this.greet = function() {
console.log("Hi, I'm " + this.name);
};
}
// method on the prototype
function Person(name) {
this.name = name; // own property — each instance needs its own
}
// Defined once, shared by every Person instance
Person.prototype.greet = function() {
console.log("Hi, I'm " + this.name);
};
const priya = new Person("Priya");
const rohan = new Person("Rohan");
priya.greet(); // "Hi, I'm Priya"
rohan.greet(); // "Hi, I'm Rohan"
// Same function object, just this changes per call
console.log(priya.greet === rohan.greet); // true
Own properties live on the instance. Methods that do not need unique per-instance data belong on the prototype. That line is where most of the judgment calls happen.
How Prototype Lookup Works
When you write priya.greet(), JavaScript looks for greet on priya itself first. It is not there. So it follows the internal [[Prototype]] link up to Person.prototype and looks there. It finds it. Done.
If it were not there either, it would keep climbing: Object.prototype is next. If it is not there, you get undefined. This chain of lookups is called the prototype chain, and it is the mechanism behind every method you call on any object in JavaScript.
The practical upshot: methods on the prototype behave exactly like methods on the instance from the caller's perspective. You write priya.greet() either way. The lookup is invisible. You only notice it when you start asking questions like "where does .toString() come from on every object ever."
Forgetting new: What Goes Wrong
Call a constructor without new and JavaScript just runs it as a regular function. No blank object gets created. this inside it is not a fresh instance, it is either the global object (in non-strict mode) or undefined (in strict mode). In non-strict mode you get no error. You just silently write properties onto window and wonder why nothing is working.
function Person(name) {
this.name = name;
}
const oops = Person("Priya"); // no new
console.log(oops); // undefined: function returned nothing
console.log(window.name); // "Priya": oops, now it's global
In strict mode this at least throws a TypeError immediately, which is easier to catch. If you are writing constructor functions today, putting "use strict" at the top of your file is a reasonable safety net.
ES6 classes solve this permanently. A class constructor throws a TypeError if you call it without new, no matter what. That is one of the reasons classes exist.
Classes Do The Same Thing, With Better Guardrails
ES6 classes are not a different object model. They are a cleaner syntax over the same constructor function and prototype setup. If you understand constructors and prototypes, you already understand what classes compile down to.
// constructor function
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function() {
console.log("Hi, I'm " + this.name);
};
// class
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log("Hi, I'm " + this.name);
}
}
// Both produce instances with the same shape
const p = new Person("Priya", 28);
p.greet(); // "Hi, I'm Priya"
With the class syntax, greet is automatically placed on Person.prototype. You do not write that out manually. The engine handles it. The result is identical to the constructor function version, but there is less surface area for mistakes.
Constructor vs Instance
Properties and methods can live in three places: on the instance, on the prototype, or on the constructor function itself. Each one is used differently.
function Person(name) {
this.name = name; // instance property: unique per object
}
Person.prototype.greet = function() { // prototype method: shared
console.log(this.name);
};
Person.count = 0; // static: lives on the constructor, not instances
const p = new Person("Priya");
p.greet(); // works. found on prototype
console.log(p.count); // undefined. instances don't see static props
console.log(Person.count); // 0. access it through the constructor
If you want to test what you just read, try this: write a Counter constructor that stores a count on this, then add increment and reset methods on the prototype. Make two counters and verify they count independently. Then check that both counters share the same increment function reference.
That small exercise covers everything in this post. Own properties, shared methods, separate instances. Once that clicks, classes will feel like a notation change rather than a concept change, because you will already know what the class body is doing behind the scenes.
REFERENCES:



