Table of contents
1.
Introduction
2.
Understanding Polymorphism  
3.
Features of Polymorphism
4.
Polymorphism with Functions and Objects
4.1.
Example
5.
Polymorphism in Functional Programming
5.1.
Example
6.
Design Patterns Leveraging Polymorphism
6.1.
Example of Strategy Pattern
7.
Types of Polymorphism in JavaScript  
7.1.
1. Ad-hoc Polymorphism  
7.1.1.
Example
7.2.
2. Parametric Polymorphism  
7.2.1.
Example
7.3.
3. Subtype Polymorphism  
7.3.1.
Example:  
7.3.2.
Another Example
8.
Method Overriding
8.1.
Example
9.
Simulating Method Overloading
9.1.
Example
10.
Frequently Asked Questions
10.1.
What is polymorphism in JavaScript?
10.2.
How does JavaScript support polymorphism?
10.3.
Why is polymorphism useful in JavaScript?
11.
Conclusion
Last Updated: Feb 9, 2025
Easy

Polymorphism in JavaScript

Author Gaurav Gandhi
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Polymorphism in JavaScript is an object-oriented programming concept that allows different objects to share the same method name but execute different behaviors based on the object calling the method. It enhances code flexibility and reusability by enabling method overriding and method overloading in different contexts.

Polymorphism in JavaScript

In this article, we will discuss method overriding, method overloading simulation, and how polymorphism works with functions, objects, and functional programming.

Understanding Polymorphism  

Polymorphism is a programming concept that allows a single function, method, or object to work in different ways depending on the context. The word "polymorphism" comes from Greek, meaning "many forms." In simpler terms, it means that one thing can behave in multiple ways.  

In JavaScript, polymorphism is often achieved through functions or methods that can operate on different types of data. For example, a single function might work with numbers, strings, or even objects, but it will behave differently depending on the input. This makes your code more flexible & reusable.  

Let’s take a simple example to understand this better. Suppose you have a function called `printValue` that can print different types of values:  


function printValue(value) {
  console.log(value);
}
printValue(10); 
printValue("Hello"); 
printValue(true); 
You can also try this code with Online Javascript Compiler
Run Code

 

Output: 

10
hello
true


Here, the `printValue` function works with numbers, strings, & booleans. It behaves differently depending on the type of input, but the function itself remains the same. This is a basic example of polymorphism in action.  

Polymorphism is not just limited to functions. It can also be applied to objects & methods. For instance, if you have different objects with the same method name, JavaScript will call the correct method based on the object type.  

Let’s look at another example:  

class Animal {
  makeSound() {
    console.log("Animal sound");
  }
}
class Dog extends Animal {
  makeSound() {
    console.log("Woof!");
  }
}
class Cat extends Animal {
  makeSound() {
    console.log("Meow!");
  }
}
const myDog = new Dog();
const myCat = new Cat();
myDog.makeSound(); 
myCat.makeSound(); 
You can also try this code with Online Javascript Compiler
Run Code

 

Output: 

Woof!
Meow!


In this example, both `Dog` & `Cat` classes have a `makeSound` method. Even though the method name is the same, the behavior is different for each class. This is another way polymorphism works in JavaScript.  

Polymorphism makes your code more modular & easier to maintain. Instead of writing separate functions or methods for each type of data, you can write one function or method that adapts to different inputs.  

Features of Polymorphism

Polymorphism in JavaScript offers several advantages:

  1. Code Reusability: Allows methods to be reused across different objects.
     
  2. Flexibility: Functions and methods can handle different data types or arguments.
     
  3. Scalability: Makes code easier to extend without modifying existing logic.
     
  4. Simplified Maintenance: Reduces redundant code, making it easier to update.

Polymorphism with Functions and Objects

JavaScript allows polymorphism with functions and objects by treating different objects in a similar way if they share the same method names.

Example

class Bird {
    fly() {
        console.log("The bird is flying");
    }
}

class Airplane {
    fly() {
        console.log("The airplane is taking off");
    }
}

function takeOff(entity) {
    entity.fly();
}

let myBird = new Bird();
let myPlane = new Airplane();

takeOff(myBird); 
takeOff(myPlane);
You can also try this code with Online Javascript Compiler
Run Code


Output: 

The bird is flying
The airplane is taking off

 

Explanation:

  • Both Bird and Airplane classes have a fly() method.
     
  • The takeOff() function calls fly(), but it works for both objects due to polymorphism.

Polymorphism in Functional Programming

JavaScript supports functional programming, where polymorphism is implemented using higher-order functions and callbacks.

Example

function execute(operation, a, b) {
    return operation(a, b);
}

function add(x, y) {
    return x + y;
}

function multiply(x, y) {
    return x * y;
}

console.log(execute(add, 5, 3)); 
console.log(execute(multiply, 5, 3)); 
You can also try this code with Online Javascript Compiler
Run Code


Output: 

8
15

 

Explanation

  • The execute function takes another function (operation) as an argument.
     
  • It calls the provided function with two numbers, allowing dynamic execution.
     
  • This demonstrates polymorphism since different functions (add, multiply) work with the same execute() function.

Design Patterns Leveraging Polymorphism

Polymorphism is widely used in design patterns to create scalable and maintainable applications. Some common patterns include:

  1. Factory Pattern: Creates different types of objects with a common interface.
     
  2. Strategy Pattern: Defines a family of algorithms and lets them be interchangeable.
     
  3. Decorator Pattern: Adds behavior to objects dynamically without modifying their structure.

Example of Strategy Pattern

class Payment {
    process(amount) {
        console.log("Processing payment of $" + amount);
    }
}

class CreditCardPayment extends Payment {
    process(amount) {
        console.log("Processing credit card payment of $" + amount);
    }
}

class PayPalPayment extends Payment {
    process(amount) {
        console.log("Processing PayPal payment of $" + amount);
    }
}
function makePayment(paymentMethod, amount) {
    paymentMethod.process(amount);
}
let creditCard = new CreditCardPayment();
let paypal = new PayPalPayment();

makePayment(creditCard, 100); 
makePayment(paypal, 50);
You can also try this code with Online Javascript Compiler
Run Code

 

Output: 

Processing credit card payment of $100
Processing PayPal payment of $50

 

Explanation

  • The base Payment class has a process() method.
     
  • Subclasses (CreditCardPayment, PayPalPayment) override process().
     
  • The makePayment() function works polymorphically with different payment methods.

Types of Polymorphism in JavaScript  

Polymorphism in JavaScript can be categorized into three main types: Ad-hoc Polymorphism, Parametric Polymorphism, & Subtype Polymorphism. Each type has its own unique way of handling multiple forms of behavior. Let’s discuss each one in detail.  

1. Ad-hoc Polymorphism  

Ad-hoc polymorphism refers to functions or methods that behave differently based on the type or number of arguments passed to them. This is also known as function overloading in some programming languages.  

In JavaScript, ad-hoc polymorphism is often implemented using conditional logic inside a function to handle different types of inputs.  

Example

function add(a, b) {
  if (typeof a === "number" && typeof b === "number") {
    return a + b;
  } else if (typeof a === "string" && typeof b === "string") {
    return a.concat(b);
  } else {
    return "Invalid input types";
  }
}


console.log(add(5, 10)); 
console.log(add("Hello, ", "World!"));
console.log(add(5, "Hello")); 
You can also try this code with Online Javascript Compiler
Run Code

 

Output:

15
 Hello, World!
Invalid input types


In this example, the `add` function behaves differently depending on the type of arguments passed. If both arguments are numbers, it performs addition. If both are strings, it concatenates them. Otherwise, it returns an error message.  

Note: Ad-hoc polymorphism is useful when you want a single function to handle multiple types of inputs without creating separate functions for each type.  

2. Parametric Polymorphism  

Parametric polymorphism is a type of polymorphism where a function or method can operate on any data type without needing to know the specific type in advance. This is commonly seen in generic functions or generic programming. In JavaScript, parametric polymorphism is often achieved using template literals or higher-order functions.  

The key idea here is that the same code can work with different types of data without requiring any changes.  

Example

Let’s create a generic function called `identity` that returns whatever value is passed to it:  

function identity(value) {
  return value;
}

console.log(identity(10)); 
console.log(identity("Hello"));
console.log(identity(true)); 
You can also try this code with Online Javascript Compiler
Run Code

 

Output:

10
Hello
true


In this example, the `identity` function works with numbers, strings, & booleans. It doesn’t need to know the type of the input in advance. This is a simple example of parametric polymorphism.  

Another common example is using arrays in JavaScript. Arrays can store any type of data, & methods like `map`, `filter`, & `reduce` work with any data type.  

const numbers = [1, 2, 3, 4];
const strings = ["apple", "banana", "cherry"];
const doubledNumbers = numbers.map((num) => num  2);
const upperCaseStrings = strings.map((str) => str.toUpperCase());
console.log(doubledNumbers); 
console.log(upperCaseStrings); 

 

Output: 

[2, 4, 6, 8]
["APPLE", "BANANA", "CHERRY"]


Here, the `map` method works with both numbers & strings. It doesn’t care about the type of data in the array. This is another example of parametric polymorphism in action.  

Note: Parametric polymorphism is useful when you want to write reusable code that can handle any data type. It reduces redundancy & makes your code more flexible.  

3. Subtype Polymorphism  

Subtype polymorphism is one of the most common forms of polymorphism in object-oriented programming. It occurs when a subclass or child class provides a specific implementation of a method that is already defined in its parent class. This allows objects of different classes to be treated as objects of a common superclass while still retaining their unique behavior.  

In JavaScript, subtype polymorphism is achieved through inheritance. When a child class inherits from a parent class, it can override the parent class’s methods to provide its own implementation.  

Example:  

Let’s create a parent class called `Shape` & two child classes called `Circle` & `Rectangle`. Each child class will override the `draw` method of the parent class to provide its own implementation.  

class Shape {
  draw() {
    console.log("Drawing a shape");
  }
}

class Circle extends Shape {
  draw() {
    console.log("Drawing a circle");
  }
}

class Rectangle extends Shape {
  draw() {
    console.log("Drawing a rectangle");
  }
}

const shapes = [new Shape(), new Circle(), new Rectangle()];

shapes.forEach((shape) => shape.draw());
You can also try this code with Online Javascript Compiler
Run Code

 

Output:  

Drawing a shape  
Drawing a circle  
Drawing a rectangle  


In this example, the `Shape` class has a `draw` method, which is overridden by the `Circle` & `Rectangle` classes. When we call the `draw` method on each object in the `shapes` array, JavaScript automatically calls the correct implementation based on the object’s type.  

This is subtype polymorphism in use. Even though all objects in the `shapes` array are treated as instances of the `Shape` class, they retain their unique behavior when the `draw` method is called.  

Another Example

Let’s take a real-world analogy. Suppose you have a parent class called `Animal` & child classes like `Dog`, `Cat`, & `Bird`. Each animal makes a different sound, so the `makeSound` method is overridden in each child class.  

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

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

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

class Bird extends Animal {
  makeSound() {
    console.log("Chirp!");
  }
}

const animals = [new Dog(), new Cat(), new Bird()];

animals.forEach((animal) => animal.makeSound());
You can also try this code with Online Javascript Compiler
Run Code


Output:  

Woof!  
Meow!  
Chirp!  


Here, the `makeSound` method behaves differently for each animal, even though all objects are treated as instances of the `Animal` class.  

Note: Subtype polymorphism is powerful because it allows you to write code that works with a general type (like `Shape` or `Animal`) while still leveraging the specific behavior of child classes.  

Method Overriding

Method overriding occurs when a subclass provides a specific implementation for a method that is already defined in its parent class. This is useful when a child class needs to modify the behavior of an inherited method.

Example

class Animal {
    speak() {
        console.log("The animal makes a sound");
    }
}
class Dog extends Animal {
    speak() {
        console.log("The dog barks");
    }
}
let myPet = new Dog();
myPet.speak(); 
You can also try this code with Online Javascript Compiler
Run Code


Output: 

The dog barks


Explanation

  • The Animal class has a speak() method.
     
  • The Dog class extends Animal and overrides the speak() method.
     
  • When speak() is called on a Dog object, it executes the overridden method in the subclass.

Simulating Method Overloading

JavaScript does not support traditional method overloading like other languages (e.g., Java, C++). However, we can simulate it by using conditional statements within a single function to handle different argument types or counts.

Example

function greet(name, age) {
    if (age === undefined) {
        console.log("Hello, " + name);
    } else {
        console.log("Hello, " + name + ". You are " + age + " years old.");
    }
}

greet("Alice"); 
greet("Bob", 25); 
You can also try this code with Online Javascript Compiler
Run Code


Output: 

Hello, Alice
Hello, Bob. You are 25 years old.


Explanation:

  • The greet function checks if the age parameter is provided.
     
  • It executes different logic based on the number of arguments passed.

Frequently Asked Questions

What is polymorphism in JavaScript?

Polymorphism in JavaScript allows functions, methods, or objects to behave differently based on their context, enabling code reusability and flexibility.

How does JavaScript support polymorphism?

JavaScript supports polymorphism through method overriding, function parameter handling, and functional programming techniques such as higher-order functions.

Why is polymorphism useful in JavaScript?

Polymorphism makes code more maintainable, reusable, and scalable by allowing different objects or functions to share common interfaces while implementing different behaviors.

Conclusion

In this article, we learned about Polymorphism in JavaScript and how it helps objects share the same method but behave differently. We explored method overriding, prototype-based inheritance, and how JavaScript supports polymorphism. Understanding this concept makes code more flexible and reusable. Using polymorphism, developers can write cleaner and more efficient JavaScript programs.

Live masterclass