Constructors in JavaScript

Introduction

A constructor runs when you create an instance with new. In classes, the constructor method initializes this. In older code, constructor functions did the same job. This chapter covers initialization rules, returning from constructors, and static methods that belong to the class itself.

Prerequisites

Class constructor

javascript
// constructor sets instance state
class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
    this.createdAt = new Date().toISOString();
  }
}
 
const user = new User("Ada", "ada@example.com");
console.log(user.name, user.createdAt);

What new Does (Simplified)

  1. Creates a new empty object
  2. Links its prototype to the class prototype
  3. Runs constructor with this bound to that object
  4. Returns the object (unless constructor returns a different object)
javascript
// Manual mental model (do not use in production)
function Person(name) {
  this.name = name;
}
 
const p = new Person("Lin");
console.log(p.name);

Parameter Validation in Constructor

javascript
// Fail fast on bad input
class Order {
  constructor(id, total) {
    if (!id) throw new Error("id required");
    if (total < 0) throw new Error("total must be non-negative");
    this.id = id;
    this.total = total;
  }
}
 
try {
  new Order("", -1);
} catch (err) {
  console.log(err.message);
}

Static Methods and Properties

Belong to the class, not each instance:

javascript
// Static factory on class
class ApiError {
  static fromResponse(status, body) {
    return new ApiError(`HTTP ${status}: ${body}`);
  }
 
  constructor(message) {
    this.message = message;
  }
}
 
const err = ApiError.fromResponse(404, "Not found");
console.log(err.message);
javascript
// Static counter
class RequestId {
  static #seq = 0;
 
  static next() {
    RequestId.#seq += 1;
    return RequestId.#seq;
  }
}
 
console.log(RequestId.next());
console.log(RequestId.next());

Private Fields with #

javascript
// True instance privacy (modern engines)
class BankAccount {
  #balance = 0;
 
  constructor(initial) {
    this.#balance = initial;
  }
 
  deposit(amount) {
    this.#balance += amount;
  }
 
  balance() {
    return this.#balance;
  }
}
 
const acct = new BankAccount(100);
acct.deposit(25);
console.log(acct.balance());

Constructor Functions (Legacy)

javascript
// Still valid; prefer class in new code
function Point(x, y) {
  this.x = x;
  this.y = y;
}
 
Point.prototype.distance = function (other) {
  const dx = this.x - other.x;
  const dy = this.y - other.y;
  return Math.hypot(dx, dy);
};
 
const a = new Point(0, 0);
const b = new Point(3, 4);
console.log(a.distance(b));

Mini Example: UUID Stub Generator

javascript
class IdGenerator {
  static #counter = 0;
 
  constructor(prefix = "id") {
    this.prefix = prefix;
  }
 
  next() {
    IdGenerator.#counter += 1;
    return `${this.prefix}-${IdGenerator.#counter}`;
  }
}
 
const gen = new IdGenerator("user");
console.log(gen.next());
console.log(gen.next());

FAQ

Must constructor be named constructor?

In a class, yes—only one constructor method (or none for empty default).

Can constructor be async?

async constructor is invalid—use a static async create() factory instead.

Static vs instance method?

Static: Math.max, factories, counters. Instance: behavior on one object's data.

What comes next?

Inheritanceextends and super.