Skip to main content

How does a class differ from a constructor function?

1. Syntax and Readability

Constructor function:

javascript
function User(name) { this.name = name; } User.prototype.greet = function () { console.log(`Hi, ${this.name}`); }; const user = new User("Alice"); user.greet();

Class:

javascript
class User { constructor(name) { this.name = name; } greet() { console.log(`Hi, ${this.name}`); } } const user = new User("Alice"); user.greet();

A class looks cleaner and more declarative, especially with inheritance. A constructor function requires manually writing out prototype, Object.create(), and so on.


2. Behavior When Called Without new

  • A constructor function can accidentally be called without new, which leads to errors (for example, this becomes undefined in strict mode or gets bound to window):

    javascript
    function User(name) { this.name = name; } const u = User("Alice"); // Error, or it creates a global window.name property
  • A class cannot be called without new, it throws an exception:

    javascript
    class User { constructor(name) { this.name = name; } } const u = User("Alice"); // TypeError: Class constructor User cannot be invoked without 'new'

This makes classes safer.


3. Classes Always Run in Strict Mode

The entire body of a class automatically runs in strict mode, even if 'use strict' is not written.

A constructor function, on the other hand, does not, unless 'use strict' is explicitly specified.


4. Class Methods Are Not Enumerable

That means methods defined inside class {} do not show up when you iterate with for...in, while methods on a constructor function's prototype are enumerable:

javascript
class A { m() {} } console.log(Object.keys(A.prototype)); // [] function B() {} B.prototype.m = function() {}; console.log(Object.keys(B.prototype)); // ["m"]

This makes classes "cleaner" for iteration and serialization.


5. Classes Cannot Declare Methods as Regular Functions

If you try to write this in a class body:

javascript
class A { m = function() {}; // SyntaxError in older versions }

you need to use class field syntax or arrow functions, which appeared later (ES2022+).


6. Classes Have No Hoisting

  • Constructor functions can be called before they are declared (because of hoisting):

    javascript
    const a = new User(); function User() {}
  • Classes cannot:

    javascript
    const a = new User(); // ReferenceError class User {}

This prevents unexpected runtime errors.


7. Inheritance Is Simpler

With constructor functions, you need to write a lot of boilerplate:

javascript
function Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(`${this.name} makes a sound`); }; function Dog(name) { Animal.call(this, name); } Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog;

With classes:

javascript
class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a sound`); } } class Dog extends Animal { speak() { console.log(`${this.name} barks`); } }

Short and clear.


Summary Table

DifferenceClassConstructor Function
Calling without newErrorWorks, but can lead to bugs
Strict modeAlways onNot by default
HoistingNonePresent
Enumerable methodsNoYes
Inheritance syntaxSimple (extends)Complex (Object.create, call)
Private fieldsYes (#field)No
ReadabilityHighLow

Short Answer

Interview ready
Premium

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