JavaScript Polymorphism

Polymorphism is one of the four fundamental concepts of Object-Oriented Programming (OOP). The word polymorphism means “many forms.” In programming, it allows the same method name or interface to produce different behaviors depending on the object or the values being used.

In JavaScript, polymorphism is commonly achieved through inheritance, method overriding, and shared interfaces. It helps developers write flexible and reusable code that works with different types of objects.

For example, a Dog and a Cat can both have a makeSound() method. When the method is called, the dog barks while the cat meows. The same method name produces different results.

In this tutorial, you will learn what polymorphism is, how it works in JavaScript, and how to implement it using practical examples.

What Is Polymorphism in JavaScript?

Polymorphism is an OOP concept that allows different objects to respond to the same method call in different ways.

Instead of writing separate code for every object type, you can use a common method name and let each object provide its own behavior.

Example of Polymorphism

class Animal {
  makeSound() {
    console.log("Animal makes a sound");
  }
}

class Dog extends Animal {
  makeSound() {
    console.log("Dog barks");
  }
}

class Cat extends Animal {
  makeSound() {
    console.log("Cat meows");
  }
}

const dog = new Dog();
const cat = new Cat();

dog.makeSound();
cat.makeSound();

Output:

Dog barks
Cat meows

In this example:

  • Animal is the parent class.
  • Dog and Cat are child classes.
  • Both child classes define their own makeSound() method.
  • The same method name produces different behavior depending on the object.

This is polymorphism through method overriding.

How Polymorphism Works in JavaScript

Polymorphism allows you to write code that works with different objects without needing to know the exact class of every object in advance.

JavaScript determines which method to call based on the object’s prototype chain and the method that is available on that object.

Consider the following example:

class Vehicle {
  start() {
    console.log("Vehicle is starting");
  }
}

class Car extends Vehicle {
  start() {
    console.log("Car engine started");
  }
}

class Bike extends Vehicle {
  start() {
    console.log("Bike engine started");
  }
}

function startVehicle(vehicle) {
  vehicle.start();
}

startVehicle(new Car());
startVehicle(new Bike());

Output:

Car engine started
Bike engine started

The startVehicle() function accepts different objects. It calls start() without checking whether the object is a car or a bike.

Each object provides its own implementation of the method.

This makes the function flexible and reduces the need for repeated conditional statements.

Method Overriding in Polymorphism

Method overriding occurs when a child class defines a method with the same name as an inherited method.

When the method is called on a child instance, JavaScript uses the child’s implementation.

Example of Method Overriding

class Employee {
  calculateSalary() {
    return 20000;
  }
}

class Developer extends Employee {
  calculateSalary() {
    return 40000;
  }
}

class Manager extends Employee {
  calculateSalary() {
    return 60000;
  }
}

const developer = new Developer();
const manager = new Manager();

console.log(developer.calculateSalary());
console.log(manager.calculateSalary());

Output:

40000
60000

The Developer and Manager classes override the inherited calculateSalary() method.

Although both objects use the same method name, the returned salary differs according to the class implementation.

Using super() with Method Overriding

Sometimes, a child class needs to extend the behavior of a parent method rather than replace it entirely.

You can use super.methodName() to call the parent implementation.

class Employee {
  display() {
    console.log("Employee details");
  }
}

class Developer extends Employee {
  display() {
    super.display();
    console.log("Developer writes code");
  }
}

const developer = new Developer();

developer.display();

Output:

Employee details
Developer writes code

The child method first calls the parent method and then adds its own behavior.

Polymorphism Using a Common Interface

JavaScript does not require unrelated objects to inherit from the same class to use polymorphism.

Objects can support the same method name and be used through a common interface. This is often called duck typing: if an object provides the behavior a function needs, the function can use that object.

Example Without Inheritance

const dog = {
  speak() {
    console.log("Woof!");
  }
};

const cat = {
  speak() {
    console.log("Meow!");
  }
};

const robot = {
  speak() {
    console.log("Robot speaking");
  }
};

function makeItSpeak(object) {
  object.speak();
}

makeItSpeak(dog);
makeItSpeak(cat);
makeItSpeak(robot);

Output:

Woof!
Meow!
Robot speaking

The three objects do not need to share a parent class. They only need to provide a compatible speak() method.

This style is useful when working with plugins, reusable functions, and objects from different parts of an application.

Polymorphism Through Method Parameters

Polymorphism can also appear when the same function or operator works with different kinds of values.

JavaScript is dynamically typed, so a function can accept different values and behave according to the operations it performs.

Example with a Function

function display(value) {
  console.log(value);
}

display("Hello JavaScript");
display(100);
display(true);

Output:

Hello JavaScript
100
true

The same function accepts a string, a number, and a boolean.

This demonstrates flexible function behavior, although it is not the same as method overriding in class-based OOP.

Example with the Addition Operator

console.log(10 + 20);
console.log("Hello " + "World");

Output:

30
Hello World

The + operator performs numeric addition with numbers and string concatenation when strings are involved. This is an example of operator overloading-like behavior built into JavaScript, rather than user-defined operator overloading.

Practical Example of Polymorphism

Imagine an online payment application that supports different payment methods, such as credit cards and digital wallets.

Each payment method can provide its own pay() implementation. The application can then process payments through a shared interface.

class CreditCardPayment {
  pay(amount) {
    console.log(`Paid ₹${amount} using a credit card`);
  }
}

class WalletPayment {
  pay(amount) {
    console.log(`Paid ₹${amount} using a digital wallet`);
  }
}

class BankTransferPayment {
  pay(amount) {
    console.log(`Paid ₹${amount} using a bank transfer`);
  }
}

function processPayment(paymentMethod, amount) {
  paymentMethod.pay(amount);
}

processPayment(new CreditCardPayment(), 1000);
processPayment(new WalletPayment(), 500);
processPayment(new BankTransferPayment(), 2000);

Output:

Paid ₹1000 using a credit card
Paid ₹500 using a digital wallet
Paid ₹2000 using a bank transfer

How This Example Works

  • Each payment class defines a pay() method.
  • Each method handles the payment differently.
  • processPayment() accepts any object that supports pay().
  • The function does not need separate logic for each payment type.

In a real payment system, each implementation would also need appropriate validation, security checks, and integration with the relevant payment service.

Types of Polymorphism in JavaScript

Polymorphism can be discussed in several forms.

TypeDescriptionJavaScript example
Subtype polymorphismDifferent related objects share a common interfaceA Dog and Cat override makeSound()
Duck typingObjects are used based on the behavior they provideDifferent objects implement speak()
Parametric polymorphismCode works across different types under a general abstractionGeneric functions in TypeScript
Ad hoc polymorphismThe same operation has different behavior for different inputsThe built-in + operator

JavaScript supports subtype polymorphism and duck typing directly. It does not provide traditional user-defined function or operator overloading in the same way as languages such as Java or C++.

TypeScript adds static type-system features that can express generic, reusable functions more explicitly.

Polymorphism vs Inheritance

Inheritance and polymorphism are related OOP concepts, but they serve different purposes.

InheritancePolymorphism
Allows a class to inherit functionality from another classAllows different objects to provide different behavior through a common interface
Commonly uses extends and superCommonly uses method overriding or shared method names
Focuses on relationships between classesFocuses on interchangeable behavior
Example: Dog extends AnimalExample: Dog and Cat implement makeSound() differently

Inheritance can help implement polymorphism, but polymorphism can also work without inheritance through compatible object interfaces.

Advantages of Polymorphism in JavaScript

Polymorphism provides several benefits when designing applications.

  • Code reusability: One function can work with different compatible objects.
  • Flexibility: New implementations can be added without rewriting the calling code.
  • Maintainability: Shared interfaces make application logic easier to organize.
  • Extensibility: New payment methods, notification channels, or file processors can implement existing behavior.
  • Reduced conditional logic: Functions can delegate behavior to the object instead of checking its type repeatedly.

Polymorphism works best when objects share a clear and meaningful interface.

Common Mistakes When Using Polymorphism

Using Different Method Names

If a function expects makeSound(), an object that only defines speak() will not satisfy that interface unless you adapt the function or object.

Use consistent method names when objects are expected to work interchangeably.

Assuming Inheritance Is Always Required

JavaScript objects can support the same interface without inheriting from a common parent class.

Use inheritance when it represents a genuine relationship. Use compatible object interfaces or composition when they better fit the design.

Confusing Overloading with Overriding

Method overriding replaces inherited behavior in a child class. JavaScript does not support traditional method overloading based solely on different parameter lists in the same way as some statically typed languages.

If you define multiple class methods with the same name, the later definition replaces the earlier one.

Ignoring Missing Methods

If a function calls object.pay() but the supplied object does not have a callable pay method, the program can throw a TypeError.

Ensure that objects satisfy the interface expected by the function, or validate the object before calling its method.

FAQs About JavaScript Polymorphism

What is polymorphism in JavaScript?

Polymorphism allows different objects to respond to the same method call in different ways. It helps create flexible and reusable code.

How do you achieve polymorphism in JavaScript?

You can achieve polymorphism through method overriding in class inheritance or by using different objects that implement the same method interface.

What is method overriding?

Method overriding occurs when a child class defines its own implementation of an inherited method.

Can polymorphism work without inheritance in JavaScript?

Yes. JavaScript supports duck typing, which allows a function to work with unrelated objects that provide the required methods.

What is a real-world example of polymorphism?

A payment application can use the same pay() method for credit cards, digital wallets, and bank transfers, with each payment method implementing its own behavior.

What is the difference between polymorphism and encapsulation?

Polymorphism focuses on interchangeable behavior through a shared interface. Encapsulation focuses on grouping data and behavior while controlling access to an object’s internal state.

Does JavaScript support method overloading?

JavaScript does not support traditional method overloading based solely on parameter types or counts. Developers can implement similar behavior using optional parameters, rest parameters, or conditional logic.

Conclusion

Polymorphism is an important OOP concept that allows different JavaScript objects to respond to the same method call in different ways.

You can implement it through method overriding, inheritance, or shared object interfaces. It helps reduce repeated code, improve flexibility, and make applications easier to extend.

By understanding polymorphism alongside inheritance and encapsulation, you can build more modular and maintainable JavaScript applications.