The `new` Operator — How a Function Becomes an Object

new is the most puzzling among the four ways this can be invoked. You write new Dog() and get an empty object — what actually happens in between?

Why can you new a function?

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

new Dog("大黄") does the following:

  1. Creates an empty object, pointing its __proto__ to Dog.prototype (see the guide at the end of this post for prototype chain details)
  2. Binds this to this empty object, then executes the constructor body
  3. this.xxx = ... inside the constructor gets attached to this object
  4. Returns this object (if the constructor doesn’t explicitly return an object)

class is syntactic sugar

// class syntax:
class Dog {
  name: string;
  constructor(name: string) {
    this.name = name; 
  }
  bark() {
    console.log(`${this.name}: woof!`);
  }
}

// Equivalent prototype syntax:
function Dog(this: any, name: string) {
  this.name = name; 
}
Dog.prototype.bark = function () {
  console.log(`${this.name}: woof!`);
};

Verifying that class is indeed a function:

console.log(typeof Dog); // "function" — class is just function
const d = new Dog("大黄");
console.log(d.bark === Dog.prototype.bark); // true — methods live on the prototype

This also explains why arrow functions as class fields aren’t shared:

class Dog {
  bark() {} // → Dog.prototype.bark (shared by all instances)
  run = () => {}; // → this.run = () => {} (each instance gets its own copy)
}

run = () => {} is equivalent to defining a regular property — written as this.run = () => {} inside the constructor, attached to the instance, bypassing prototype sharing.

More

new answers “where objects come from”, but not “how methods on the prototype chain are found”:

  • What’s the relationship between __proto__ and prototype?
  • How does the prototype chain look up methods layer by layer?
  • How do instanceof and hasOwnProperty work under the hood?

Dive deeper here: Prototype Chain — From new an Object to the Essence of Method Sharing