Skip to main content

Multiple constructors in a class

A JavaScript class can have exactly one constructor(). The language has no overloading by argument count or type, so "several constructors" are imitated with argument checks, a parameter object, static factories or inheritance.

Theory

TL;DR

  • Two constructor() declarations in one class give SyntaxError: A class may only have one constructor.
  • Method overloading in the Java or C# sense simply does not exist in JavaScript.
  • The simplest replacement: one constructor that inspects its own arguments.
  • With many parameters a parameter object with destructuring and defaults reads better.
  • The cleanest approach in real projects: static factory methods such as User.fromName() and User.fromObject().
  • Genuinely different shapes of data are often better expressed as different subclasses.

Quick example

javascript
class User { constructor(name) { this.name = name; } // SyntaxError: a constructor cannot be declared twice constructor(name, age) { this.name = name; this.age = age; } }

SyntaxError: A class may only have one constructor

Why several constructors are impossible

In JavaScript a function has no signature: the number and types of arguments are not part of its identity. new User("Tim") and new User("Alex", 25) both land in the very same function, and the missing arguments are simply undefined. The engine therefore has nothing to dispatch on, and a repeated constructor declaration is rejected at the syntax level, before the code ever runs.

So the flexibility has to be built inside the single constructor, or next to it.

Option 1: checking arguments inside one constructor

javascript
class User { constructor(name, age) { if (typeof age === "undefined") { this.name = name; this.age = "unknown"; } else { this.name = name; this.age = age; } } } const u1 = new User("Tim"); const u2 = new User("Alex", 25); console.log(u1); // { name: "Tim", age: "unknown" } console.log(u2); // { name: "Alex", age: 25 }

This works like "overloading by argument count". It is fine while there are one or two checks; beyond that the constructor quickly turns into a pile of if statements.

Option 2: a parameter object and default values

When there are many parameters, taking an object is more convenient:

javascript
class User { constructor({ name, age = null, email = null } = {}) { this.name = name; this.age = age; this.email = email; } } const u1 = new User({ name: "Tim" }); const u2 = new User({ name: "Alex", email: "alex@example.com" }); console.log(u2);

The call site reads more clearly, argument order stops mattering, and the = {} lets you construct the object with no arguments at all.

For a small number of fields, plain default values are enough:

javascript
class Point { constructor(x = 0, y = 0) { this.x = x; this.y = y; } } const a = new Point(); // (0, 0) const b = new Point(10); // (10, 0) const c = new Point(5, 7); // (5, 7)

One constructor, but three legal ways to call it.

Option 3: static factory methods

This is the most popular approach in real projects: instead of several constructors you write several factories whose names explain the intent.

javascript
class User { constructor(name, age) { this.name = name; this.age = age; } static fromName(name) { return new User(name, null); } static fromObject(obj) { return new User(obj.name, obj.age); } } const u1 = User.fromName("Tim"); const u2 = User.fromObject({ name: "Alex", age: 30 }); console.log(u1, u2);

Formally these are ordinary static methods that return an instance, but to the user of the class they look exactly like "different constructors" and can carry speaking names such as fromJson or fromDatabaseRow.

Option 4: inheritance

If the different ways of creating an object really mean different fields and behaviour, express that as a class hierarchy where each child has its own constructor:

javascript
class User { constructor(name) { this.name = name; } } class Admin extends User { constructor(name, permissions) { super(name); this.permissions = permissions; } } const u = new User("Tim"); const a = new Admin("Alex", ["edit", "delete"]);

A summary of the approaches:

ApproachAllowedExample
Several constructor()No, a syntax errornone
One constructor with argument checksYesif (typeof age === "undefined") ...
Parameter objectYesconstructor({ name, age }) {}
Factory methodsYesUser.fromName() / User.fromObject()
InheritanceYesclass Admin extends User
Optional parametersYesconstructor(x = 0, y = 0)

The conclusion: a class holds a single constructor, yet the same flexibility is easy to reach through checks, factories or inheritance.

Common mistakes

  • Trying to carry constructor overloading over from Java or C#. It does not exist in JavaScript, and the error appears at parse time.
  • A constructor that has grown into a long chain of if (arguments.length === ...). That is the signal to move to factory methods.
  • Writing if (!age) instead of if (typeof age === "undefined"): 0 and an empty string are falsy too, so valid data is silently replaced by the default.
  • A parameter object without the trailing = {}: then new User() throws a TypeError, because undefined cannot be destructured.
  • A factory method hardcoding new User(...) instead of new this(...): inherited by a subclass, such a method still returns the parent type.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.