Understanding the new Keyword in JavaScript: Object Creation Under the Hood
A developer who likes to builds on his ideas ..
Every time you write
new SomeFunction(), JavaScript quietly does four things behind the scenes. This article pulls back the curtain — step by step, diagram by diagram.
What Does new Actually Do?
JavaScript is not a class-based language at its core. Beneath the class syntax sugar introduced in ES6 lies a prototype-based system where objects inherit directly from other objects. The new keyword is the bridge between constructor functions and object instances, and understanding it unlocks how JavaScript's inheritance model truly works.
When you invoke a function with new, JavaScript performs these four steps automatically:
Creates a brand-new empty object
{}Sets the prototype — links the new object's internal
[[Prototype]]to the constructor's.prototypepropertyBinds
this— runs the constructor function withthispointing to the new objectReturns the new object — unless the constructor explicitly returns a different object
Constructor Functions
A constructor function is a regular JavaScript function — with one convention: it is meant to be called with new, and its name starts with a capital letter (by community convention).
function Person(name, age) {
this.name = name;
this.age = age;
}
Without new, calling Person("Alice", 30) would run the function normally, and this would be the global object (sloppy mode) or undefined (strict mode).
With new, everything changes:
const alice = new Person("Alice", 30);
console.log(alice.name); // "Alice"
console.log(alice.age); // 30
The Object Creation Process, Step by Step
Diagram — Constructor → Instance Creation Flow
Step 1 — A blank object is born
// JavaScript does this internally:
const obj = Object.create(Person.prototype);
Step 2 — The prototype chain is linked
The new object's [[Prototype]] slot is pointed at Person.prototype. This is what makes the object an instance of Person.
Object.getPrototypeOf(alice) === Person.prototype; // true
alice instanceof Person; // true
Step 3 — The constructor runs with this = new object
// Inside the constructor, this === obj (the new empty object)
this.name = "Alice"; // obj.name = "Alice"
this.age = 30; // obj.age = 30
Step 4 — The object is returned
Unless Person explicitly returns another object, JavaScript returns this automatically. No return statement needed.
Edge case: If a constructor returns a primitive, JavaScript ignores it and still returns
this. If it returns a plain object{}, that object is returned instead and your constructed instance is discarded.
How new Links Prototypes
Every function automatically gets a .prototype property. Methods added to it are shared across all instances — never copied.
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function () {
return `Hi, I'm \({this.name} and I'm \){this.age} years old.`;
};
const alice = new Person("Alice", 30);
const bob = new Person("Bob", 25);
console.log(alice.greet()); // "Hi, I'm Alice and I'm 30 years old."
console.log(bob.greet()); // "Hi, I'm Bob and I'm 25 years old."
// Both instances share the SAME function — not copied
console.log(alice.greet === bob.greet); // true
When you call alice.greet(), JavaScript traverses the chain:
Does
aliceowngreet? No.Does
Person.prototypeowngreet? Yes — found it.
Instances Created from Constructors
console.log(alice instanceof Person); // true
console.log(alice instanceof Object); // true (everything is!)
console.log(alice instanceof Array); // false
Own properties vs. prototype properties
| Property | Belongs to | hasOwnProperty |
|---|---|---|
name, age |
The instance | true |
greet |
Person.prototype |
false |
toString, hasOwnProperty |
Object.prototype |
false |
Per-instance data lives on the instance; shared behaviour lives on the prototype.
Simulating new Yourself
function myNew(Constructor, ...args) {
// Steps 1 & 2: create object and link prototype
const obj = Object.create(Constructor.prototype);
// Step 3: run the constructor with this = obj
const result = Constructor.apply(obj, args);
// Step 4: return the new object (or constructor's explicit object return)
return result instanceof Object ? result : obj;
}
const charlie = myNew(Person, "Charlie", 28);
console.log(charlie.greet()); // "Hi, I'm Charlie and I'm 28 years old."
console.log(charlie instanceof Person); // true
new with ES6 Classes
ES6 class syntax is syntactic sugar — JavaScript compiles it to the same constructor + prototype pattern under the hood.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound.`;
}
}
const dog = new Animal("Rex");
console.log(dog.speak()); // "Rex makes a sound."
console.log(typeof Animal); // "function" — still a function!
console.log(dog instanceof Animal); // true
The speak method lives on Animal.prototype, not on dog. The only practical difference from a plain constructor: calling a class without new throws a TypeError. Constructor functions have no such guard.
Common Mistakes
Forgetting new
const oops = Person("Dave", 40); // no new!
console.log(oops); // undefined
console.log(window.name); // "Dave" — leaked to the global object
Replacing the prototype after creating instances
Person.prototype = { greet() { return "hello"; } }; // replaces the object!
alice.greet(); // TypeError — alice still points to the OLD prototype
Arrow functions can't be constructors
const Broken = (name) => { this.name = name; };
new Broken("x"); // TypeError: Broken is not a constructor
Quick Reference
// 1. Define a constructor
function Car(make, model) {
this.make = make;
this.model = model;
}
// 2. Add shared methods
Car.prototype.describe = function () {
return `\({this.make} \){this.model}`;
};
// 3. Create instances
const car1 = new Car("Toyota", "Camry");
const car2 = new Car("Honda", "Civic");
// 4. Verify prototype links
Object.getPrototypeOf(car1) === Car.prototype; // true
car1.describe === car2.describe; // true — shared!
car1.hasOwnProperty("make"); // true — own property
car1.hasOwnProperty("describe"); // false — inherited
Key Takeaways
newruns four implicit steps: create object → link prototype → bindthis→ return objectMethods on
Constructor.prototypeare shared across all instances, not copiedThe prototype chain is a live lookup, not a data copy
ES6
classcompiles to the same constructor + prototype patterninstanceofwalks the prototype chain — it does not check a type tagArrow functions cannot be constructors
If this article helped you, share it with someone learning JavaScript internals. Prototype chains are one of those concepts that suddenly make everything click.


