Object Inheritance
Object inheritance is a fundamental concept in JavaScript, allowing objects to inherit properties and methods from other objects. This is typically done using prototypes.
Prototypal Inheritance
Prototypal inheritance in JavaScript allows an object to inherit properties and methods from another object.
const person = {
greet() {
console.log(`Hello, my name is ${this.name}`);
}
};
const john = Object.create(person);
john.name = 'John';
john.greet(); // "Hello, my name is John"
Object.create()
: Creates a new object with the specified prototype object and properties.john.greet()
: Calls the inheritedgreet
method from theperson
object.
Constructor Functions
Constructor functions provide a way to create multiple instances of an object type.
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
const john = new Person('John');
const jane = new Person('Jane');
john.greet(); // "Hello, my name is John"
jane.greet(); // "Hello, my name is Jane"
Person
: Constructor function that initializes a new object with aname
property.Person.prototype.greet
: Adds a method to thePerson
prototype that can be called on all instances ofPerson
.new Person('John')
: Creates a new instance ofPerson
with the nameJohn
.
ES6 Classes
ES6 introduced classes, which are syntactic sugar over the existing prototypal inheritance.
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
const john = new Person('John');
const jane = new Person('Jane');
john.greet(); // "Hello, my name is John"
jane.greet(); // "Hello, my name is Jane"
class Person
: Declares a classPerson
with a constructor and agreet
method.constructor(name)
: The constructor initializes thename
property.new Person('John')
: Creates a new instance of thePerson
class with the nameJohn
.
Extending Classes
Classes can be extended to create subclasses.
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
class Employee extends Person {
constructor(name, jobTitle) {
super(name);
this.jobTitle = jobTitle;
}
work() {
console.log(`${this.name} is working as a ${this.jobTitle}`);
}
}
const john = new Employee('John', 'Developer');
john.greet(); // "Hello, my name is John"
john.work(); // "John is working as a Developer"
class Employee extends Person
: Declares a classEmployee
that extends thePerson
class.super(name)
: Calls the constructor of the parent classPerson
.john.work()
: Calls thework
method defined in theEmployee
class.
Composition over Inheritance
In some cases, composition can be a better alternative to inheritance. Composition allows you to create complex types by combining objects.
const canEat = {
eat() {
console.log('Eating');
}
};
const canWalk = {
walk() {
console.log('Walking');
}
};
const person = Object.assign({}, canEat, canWalk);
person.eat(); // "Eating"
person.walk(); // "Walking"
canEat
: An object with aneat
method.canWalk
: An object with awalk
method.Object.assign({}, canEat, canWalk)
: Creates a new object that combines properties fromcanEat
andcanWalk
.
Practical Examples and Best Practices
Using inheritance and composition in practical scenarios can help you design more flexible and reusable code. Here are some examples and best practices:
Inheritance
: Use inheritance when you have a clear hierarchy and shared behavior that can be reused.
Composition
: Use composition when you need to combine behaviors or when inheritance doesn't fit well with your design.
// Inheritance example
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}
const dog = new Dog('Rex');
dog.speak(); // "Rex barks."
// Composition example
const canBark = {
bark() {
console.log('Barking');
}
};
const dog = Object.assign({}, canEat, canWalk, canBark);
dog.eat(); // "Eating"
dog.walk(); // "Walking"
dog.bark(); // "Barking"
Inheritance example
: TheDog
class extends theAnimal
class and overrides thespeak
method.Composition example
: Thedog
object combines behaviors fromcanEat
,canWalk
, andcanBark
.
FAQ
Q: When should I use inheritance?
A: Use inheritance when you have a clear hierarchy and shared behavior that can be reused across multiple subclasses. Inheritance works well when there is a "is-a" relationship between the parent and child classes.
Q: When should I use composition?
A: Use composition when you need to combine behaviors or when inheritance doesn't fit well with your design. Composition is useful when there is a "has-a" relationship, allowing you to create more flexible and reusable components.
Q: Can I mix inheritance and composition?
A: Yes, you can mix inheritance and composition to create more complex and flexible designs. Use inheritance for shared behavior and hierarchy, and use composition to combine different behaviors as needed.