How does a class differ from a constructor function?
1. Syntax and Readability
Constructor function:
function User(name) {
this.name = name;
}
User.prototype.greet = function () {
console.log(`Hi, ${this.name}`);
};
const user = new User("Alice");
user.greet();Class:
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,thisbecomesundefinedin strict mode or gets bound towindow):javascriptfunction 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:javascriptclass 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:
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:
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):
javascriptconst a = new User(); function User() {} -
Classes cannot:
javascriptconst 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:
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:
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
| Difference | Class | Constructor Function |
|---|---|---|
Calling without new | Error | Works, but can lead to bugs |
| Strict mode | Always on | Not by default |
| Hoisting | None | Present |
| Enumerable methods | No | Yes |
| Inheritance syntax | Simple (extends) | Complex (Object.create, call) |
| Private fields | Yes (#field) | No |
| Readability | High | Low |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.