# The new Keyword in JavaScript: What Actually Happens

### **Problem**

You've written constructor functions. You've used `new`. But if someone asked you to *explain* what JavaScript does internally when `new` runs — step by step — could you?

Most developers can't, and that gap causes real bugs: unexpected `undefined` properties, broken prototype chains, and confusion when constructor functions behave differently with and without `new`.

**This post fixes that.**

* * *

## What `new` Does

When you write:

```js
const dog = new Animal("Rex");
```

JavaScript executes four steps internally, in this order:

**Step 1 — Create a fresh object**: An empty object `{}` is created.

**Step 2 — Link the prototype**: The new object's `[[Prototype]]` is set to `Animal.prototype`. This is what makes `instanceof` work and enables method lookup via the prototype chain.

**Step 3 — Run the constructor**: The constructor function (`Animal`) is called with `this` bound to the new object. Any property assignments inside the constructor land on this object.

**Step 4 — Return the object**: Unless the constructor explicitly returns a *different* object, the new object is returned automatically.

Here's that flow visually:---

## Constructor Functions

A constructor function is just a regular function — the convention is to capitalize it. The magic isn't in the function itself, it's in calling it with `new`.

```js
function Animal(name, sound) {
  this.name = name;
  this.sound = sound;
}

// Method lives on the prototype — shared across all instances
Animal.prototype.speak = function () {
  return `${this.name} says ${this.sound}`;
};

const dog = new Animal("Rex", "woof");
const cat = new Animal("Miso", "meow");

console.log(dog.speak());  // Rex says woof
console.log(cat.speak());  // Miso says meow
```

**Why put** `speak` **on the prototype, not inside the constructor?**

If you defined `speak` as `this.speak = function() {...}` inside the constructor, every instance would get its own copy of that function — wasted memory. By putting it on `Animal.prototype`, all instances share one copy and look it up via the prototype chain.

* * *

## The Object Creation Process, Step by Step

Here's a manual recreation of what `new` does — without using `new`:

```js
function manualNew(Constructor, ...args) {
  // Step 1: create empty object
  const obj = {};

  // Step 2: link prototype
  Object.setPrototypeOf(obj, Constructor.prototype);

  // Step 3: run constructor with `this` = new object
  const result = Constructor.apply(obj, args);

  // Step 4: return the new object (or constructor's return if it's an object)
  return result instanceof Object ? result : obj;
}

function Vehicle(make, model) {
  this.make = make;
  this.model = model;
}
Vehicle.prototype.describe = function () {
  return `${this.make} ${this.model}`;
};

const car = manualNew(Vehicle, "Toyota", "Camry");
console.log(car.describe()); // Toyota Camry
console.log(car instanceof Vehicle); // true
```

Property lookup order:

1.  Check the instance itself (`d.name` → found)
    
2.  Check `Dog.prototype` (`d.breed` → found)
    
3.  Check `Object.prototype` (`.hasOwnProperty`, `.toString`, etc.)
    
4.  `null` → `undefined`
    

Here's what the prototype chain looks like:---

## Instances from Constructors

Multiple instances from the same constructor share the prototype but own their own data:

```js
function Counter(start = 0) {
  this.count = start;
}

Counter.prototype.increment = function () {
  this.count += 1;
  return this;
};

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

const a = new Counter(0);
const b = new Counter(10);

a.increment().increment();
b.increment();

console.log(a.value()); // 2
console.log(b.value()); // 11

// They share the prototype methods but not the data
console.log(a.increment === b.increment); // true  (same function reference)
console.log(a.count === b.count);         // false (own properties, separate values)
```

* * *

## What Happens Without `new`

Call a constructor without `new` and `this` points to the global object (or is `undefined` in strict mode):

```js
"use strict";

function Point(x, y) {
  this.x = x;
  this.y = y;
}

const p = Point(3, 4); // TypeError: Cannot set properties of undefined
```

Without strict mode, the x and y properties silently pollute the global object — a notoriously confusing bug.

**Guard against misuse:**

```js
function Point(x, y) {
  if (!(this instanceof Point)) {
    return new Point(x, y);
  }
  this.x = x;
  this.y = y;
}
```

Or just use `class` syntax (see trade-offs below).

* * *

## Results

After reading this, you should be able to:

*   Predict the exact output of any `new` call
    
*   Explain why methods go on `.prototype` rather than inside the constructor
    
*   Debug `undefined` property bugs caused by missing `new`
    
*   Implement `new` manually — useful for meta-programming and polyfills
    

* * *

## Trade-offs

`new` **+ constructor functions vs ES6** `class`: Both compile to the same prototype mechanism. `class` syntax adds constructor enforcement (calling a class without `new` throws automatically), cleaner inheritance via `extends`, and better readability. Prefer `class` in new code — but understand that it's not a different system, just a cleaner syntax for the same one.

**Shared prototype mutation**: All instances share the same prototype object. If you add a property to `Dog.prototype` at runtime, every existing instance immediately sees it. Useful sometimes, surprising when it happens by accident.

**Performance**: Prototype-based method lookup is fast but not free. For extremely hot paths (millions of calls), inlining methods directly on instances can be faster, at the cost of memory.

`new` **returning an explicit object**: If the constructor returns a plain object, `new` gives you that object instead of the auto-created one. This breaks `instanceof` and is almost always a mistake.

```js
function Weird() {
  return { surprise: true }; // new Weird() instanceof Weird → false
}
```

* * *

## Conclusion

The `new` keyword is four steps in sequence: create, link, run, return. Every behavior you observe — `instanceof`, inherited methods, shared state, constructor-less calls breaking — follows directly from those four steps. Internalize them and constructor functions become completely predictable.

The natural next step is ES6 `class` syntax, which wraps this mechanism in a safer, more expressive API without changing the underlying model.

* * *

## Further Reading

*   [MDN: `new` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new)
    
*   [MDN: Object prototypes](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes)
    
*   [You Don't Know JS: `this` & Object Prototypes](https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed/this-object-prototypes)
    
*   [MDN: `class` syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)
    
*   [MDN: `Object.create()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create) — for the prototype-only pattern without constructors
