In JavaScript, class inheritance is a mechanism that allows a class to inherit properties and methods from another class. This enables you to create a hierarchy of classes, where a subclass can reuse and extend the functionality of a superclass. JavaScript supports prototype-based inheritance, and with the introduction of ES6 (ECMAScript 2015), it also provides a more traditional class syntax.
Here’s an example of class inheritance using the ES6 class syntax:
// Superclass (Parent class) class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a sound.`); } } // Subclass (Child class) inheriting from Animal class Dog extends Animal { constructor(name, breed) { // Call the constructor of the superclass super(name); this.breed = breed; } // Override the speak method speak() { console.log(`${this.name} barks!`); } // New method specific to Dog fetch() { console.log(`${this.name} fetches the ball.`); } } // Create instances of the classes const genericAnimal = new Animal('Generic Animal'); const myDog = new Dog('Buddy', 'Golden Retriever'); // Call methods on instances genericAnimal.speak(); // Output: Generic Animal makes a sound. myDog.speak(); // Output: Buddy barks! myDog.fetch(); // Output: Buddy fetches the ball.
It’s important to note that JavaScript supports prototypal inheritance at its core. The class syntax introduced in ES6 is syntactic sugar over the existing prototype-based inheritance system. Under the hood, the class keyword is creating constructor functions and adding methods to their prototypes.
Here’s an example demonstrating the use of getters and setters in a class:
class Circle { constructor(radius) { // Private property this._radius = radius; } // Getter for the radius property get radius() { return this._radius; } // Setter for the radius property set radius(newRadius) { if (newRadius > 0) { this._radius = newRadius; } else { console.log("Radius must be a positive value."); } } // Getter for computed property: area get area() { return Math.PI * this._radius ** 2; } } // Create an instance of the Circle class const myCircle = new Circle(5); // Use the getter for the radius property console.log(myCircle.radius); // Output: 5 // Use the setter to change the radius property myCircle.radius = 7; // Use the getter for the computed property: area console.log(myCircle.area); // Output: 153.93804002589985
In this example:
The get radius() method is a getter for the radius property.
Let’s go through examples of a superclass, a subclass, and inheritance in JavaScript.
Example 1: Superclass (Base Class) – Animal
class Animal { constructor(name, sound) { this.name = name; this.sound = sound; } makeSound() { console.log(`${this.name} says ${this.sound}`); } } // Creating an instance of the superclass const genericAnimal = new Animal('Generic Animal', 'generic sound'); // Using the superclass method genericAnimal.makeSound(); // Output: Generic Animal says generic sound
In this example, we have a superclass called Animal. It has a constructor that takes name and sound as parameters and a method makeSound that logs the sound the animal makes.
Example 2: Subclass – Dog (Extending Animal)
class Dog extends Animal { constructor(name, breed) { // Calling the constructor of the superclass (Animal) super(name, 'bark'); this.breed = breed; } fetch() { console.log(`${this.name} fetches the ball.`); } // Overriding the makeSound method of the superclass makeSound() { console.log(`${this.name} barks!`); } } // Creating an instance of the subclass const myDog = new Dog('Buddy', 'Golden Retriever'); // Using methods from both the superclass and subclass myDog.makeSound(); // Output: Buddy barks! myDog.fetch(); // Output: Buddy fetches the ball.
Explanation:
class ,subclass,super class and inheritance :examples with explanation
Let’s go through examples of a superclass, a subclass, and inheritance in JavaScript.
Example 1: Superclass (Base Class) – Shape
class Shape { constructor(color) { this.color = color; } draw() { console.log(`Drawing a shape with color ${this.color}`); } } // Creating an instance of the superclass const genericShape = new Shape('red'); // Using the superclass method genericShape.draw(); // Output: Drawing a shape with color red
Example 2: Subclass – Circle (Extending Shape)
class Circle extends Shape { constructor(color, radius) { // Calling the constructor of the superclass (Shape) super(color); this.radius = radius; } calculateArea() { const area = Math.PI * this.radius ** 2; console.log(`Area of the circle: ${area}`); } // Overriding the draw method of the superclass draw() { console.log(`Drawing a circle with color ${this.color} and radius ${this.radius}`); } } // Creating an instance of the subclass const myCircle = new Circle('blue', 5); // Using methods from both the superclass and subclass myCircle.draw(); // Output: Drawing a circle with color blue and radius 5 myCircle.calculateArea();// Output: Area of the circle: 78.53981633974483
Explanation:
Let’s look at examples for both variables and functions:
console.log(x); // Output: undefined var x = 5; console.log(x); // Output: 5
Function Hoisting:
sayHello(); // Output: Hello, hoisted function! function sayHello() { console.log("Hello, hoisted function!"); }
In this example, the entire function declaration function sayHello() {…} is hoisted to the top of the scope, so the function can be called before the declaration in the code.
console.log(y); // Throws a ReferenceError let y = 10;
Unlike var, let and const declarations are hoisted, but they are not initialized to undefined. Therefore, attempting to access them before the declaration in the code results in a ReferenceError.
Note:
It’s considered good practice to declare variables at the top of their scope to avoid unexpected behavior due to hoisting. Additionally, using let and const helps in preventing some of the issues associated with hoisting and encourages better variable scoping practices.
Unlike function declarations, class declarations are not hoisted in JavaScript.
Let me clarify this:
// This will NOT work, and it will throw a ReferenceError const cat = new Animal(); // ReferenceError: Animal is not defined class Animal { constructor() { this.type = 'Cat'; } }
This is in contrast to function declarations, where the entire function is hoisted and can be called before its actual position in the code.
// This works because function declarations are hoisted sayHello(); // Output: Hello, hoisted function! function sayHello() { console.log("Hello, hoisted function!"); }
Let’s create a simple application to showcase hoisting in JavaScript.
We’ll create a function and a variable, both declared and used before their actual positions in the code.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hoisting Example</title> </head> <body> <script> // Example 1: Variable Hoisting console.log(message); // Output: undefined var message = "Hello, hoisted variable!"; console.log(message); // Output: Hello, hoisted variable! // Example 2: Function Hoisting sayGreetings(); // Output: Greetings from the hoisted function! function sayGreetings() { console.log("Greetings from the hoisted function!"); } </script> </body> </html>
javascript hoisting
In this example:
When you open this HTML file in a browser, you should see the expected outputs in the console. This simple application illustrates how hoisting works with both variables and functions in JavaScript.
Here’s a quiz with 10 questions related to JavaScript Class Inheritance:
a) Copying properties from one object to another
b) Creating a new class based on an existing class
c) Extending the length of a class
a) create class SubClass extends BaseClass
b) class SubClass : BaseClass
c) class SubClass extends BaseClass
a) superclass
b) this.super()
c) super
a) The subclass
b) The superclass
c) The current instance of the class
a) To call the constructor of the superclass
b) To create a new instance of the subclass
c) To access static methods of the superclass
a) No, it’s not allowed
b) Yes, it’s allowed
a) Increase the number of properties in the superclass
b) Create a new class that inherits properties and methods from another class
c) Reduce the functionality of a class
a) this.methodName()
b) super.methodName()
c) BaseClass.methodName()
a) No, it’s not allowed
b) Yes, it’s allowed
a) It reduces code complexity
b) It allows for code reuse and extension
c) It enforces strict encapsulation
Answers:
1-b) Creating a new class based on an existing class
2-c) class SubClass extends BaseClass
3-c) super
4-b) The superclass
5-a) To call the constructor of the superclass
6-b) Yes, it’s allowed
7-b) Create a new class that inherits properties and methods from another class
8-b) super.methodName()
9-b) Yes, it’s allowed
10-b) It allows for code reuse and extension
Here’s a quiz related to the concepts of hoisting in JavaScript.
Each question has multiple-choice answers. Feel free to use this quiz for practice:
a) Running code before it’s written
b) Moving declarations to the top of the scope during compilation
c) Creating variables without declarations
a) Variable declarations using var
b) Variable assignments
c) Both a and b
a) It throws a SyntaxError
b) It throws a ReferenceError
c) It outputs undefined
a) No
b) Yes
a) Function declarations
b) Class declarations
c) Variable declarations using let and const
a) get
b) return
c) getter
a) The process of moving code to the top of the scope
b) The bundling of data with the methods that operate on the data
c) The way functions are hoisted in JavaScript
a) Public method
b) Getter
c) Setter
a) Encapsulation of private properties
b) Improved code readability
c) Both a and b
a) It throws a SyntaxError
b) It throws a ReferenceError
c) It works without any issues
a) Yes
b) No
a) Variable declarations using let
b) Function expressions
c) Function declarations
a) It enforces privacy for variables
b) It indicates that a variable should be hoisted
c) It’s a syntax error
a) Variable initializations
b) Function expressions
c) Variable and function declarations
a) super
b) this
c) parent
Answers:
1-b) Moving declarations to the top of the scope during compilation
2-a) Variable declarations using var
3-c) It outputs undefined
4-b) Yes
5-c) Variable declarations using let and const
6-a) get
7-b) The bundling of data with the methods that operate on the data
8-b) Getter
9-c) Both a and b
10-b) It throws a ReferenceError
11-b) No
12-a) Variable declarations using let
13-a) It enforces privacy for variables
14-c) Variable and function declarations
15-a) super