Polymorphism enables a single function or method to exhibit different behaviors based on the context or object type it operates on.
When inherited properties or methods from a parent object are unsuitable, a child object can define its own member with the same name, overriding the parent's implementation. This process is known as overriding.
Polymorphism encompasses both overloading and overriding. Overloading involves multiple methods with the same name but different parameters, while overriding redefines a method in a subclass.
function Person(name, age) {
this.name = name;
this.age = age;
}
let person1 = new Person('Alice', 25);
console.log(person1.toString()); // Output: [object Object]
let numbers = [10, 20, 30];
console.log(numbers.toString()); // Output: 10,20,30
let currentDate = new Date();
console.log(currentDate.toString()); // Output: e.g., Mon Sep 20 2024 12:34:56 GMT+0000
let person2 = { name: 'Bob', age: 30 };
console.log(person2.toString()); // Output: [object Object]
To define custom behavior, override the method in the object's prototype or directly in the object.
// Override in prototype
Person.prototype.toString = function() {
return `{name: "${this.name}", age: ${this.age}}`;
};
console.log(person1.toString()); // Output: {name: "Alice", age: 25}
// Override in object literal
let person3 = {
name: 'Charlie',
age: 35,
toString: function() {
return `{name: "${this.name}", age: ${this.age}}`;
}
};
console.log(person3.toString()); // Output: {name: "Charlie", age: 35}
Custom Inheritance
If an entire parent object is unsuitable, replace the child object's prototype with a new parent.
Method 1: Using __proto__ (May have compatibility issues)
function Employee(id, salary) {
this.id = id;
this.salary = salary;
}
let emp1 = new Employee('E001', 50000);
let emp2 = new Employee('E002', 60000);
console.log(emp1, emp2);
let manager = { department: 'IT', role: 'Lead' };
emp2.__proto__ = manager;
console.log(emp1, emp2); // Only emp2 inherits manager properties
Method 2: Using Object.setPrototypeOf()
Set the prototype of a child object to a new parent.
function Employee(id, salary) {
this.id = id;
this.salary = salary;
}
let emp3 = new Employee('E003', 55000);
let emp4 = new Employee('E004', 65000);
console.log(emp3, emp4);
let director = { division: 'Operations', level: 'Executive' };
Object.setPrototypeOf(emp4, director);
console.log(emp3, emp4);
Changing the Prototyep for Multiple Child Objects
Modify the constructor's prototype proprety to affect all instances created afterward. Ensure this change occurs before creating any instances.
let company = { location: 'New York', industry: 'Tech' };
function Worker(empId, position) {
this.empId = empId;
this.position = position;
}
// Change prototype before instantiation
Worker.prototype = company;
let worker1 = new Worker('W001', 'Developer');
let worker2 = new Worker('W002', 'Designer');
console.log(worker1, worker2);
console.log(worker1.location, worker2.location); // Output: New York New York
console.log(worker1.industry, worker2.industry); // Output: Tech Tech