Session 8
Javascript Classes
JavaScript Classes, introduced in ES6, provide a clean, syntactic sugar over JavaScript's prototype-based inheritance, enabling true object-oriented programming (OOP) patterns. While JavaScript has always supported objects and prototypes, classes offer a familiar, template-driven approach to defining blueprints for objects with shared properties and methods. This session shifts focus from procedural scripting to OOP design, covering class declarations, constructors, instantiation, getters/setters, and inheritance.
Objectives
- Understand OOP architecture in JavaScript
- Define classes and instantiate objects with methods
- Implement getters and setters for controlled property access
- Apply inheritance using extends and super
- Solve hands-on exercises modeling real-world entities (library books, products)
What is a JavaScript Class?
- A class is a template/blueprint for creating objects.
- It encapsulates data (properties) and behavior (methods).
- Under the hood, classes still use JavaScript’s prototype chain, but the syntax is more readable and maintainable.
Class Declarations vs. Expressions
| Type | Syntax | Hoisting/Scope |
|---|---|---|
| Declaration | class MyClass {} | Not hoisted. Must be defined before use. Global/module scope. |
| Expression | const MyClass = class {} | Runs immediately. Scope limited to assignment. Can be named or unnamed. |
Constructor & Instantiation
- The constructor() method runs automatically when a new object is created.
- Used to initialize instance properties.
- Objects are instantiated using the new keyword.
class Bike {
constructor(make, year) {
this.make = make;
this.year = year;
}
getAge() {
return new Date().getFullYear() - this.year;
}
}
const myBike = new Bike("Honda", 2021);
console.log(myBike.getAge()); // e.g., 5
Getters & Setters
- Allow controlled access and validation for internal properties.
- Syntax uses get and set keywords.
Important: Getter/setter names must not match the internal property name to avoid infinite recursion.
class User {
constructor(name) { this._name = name; }
get name() { return this._name; }
set name(val) {
if (val.length > 0) this._name = val.toUpperCase();
}
}
Inheritance (extends & super)
- Child classes inherit properties/methods from parent classes using
extends. super()must be called in the child constructor before accessingthis.- Enables code reuse, method overriding, and polymorphism.
class Animal {
constructor(name) { this.name = name; }
speak() { return `${this.name} makes a sound.`; }
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // Calls parent constructor
this.breed = breed;
}
speak() { return `${this.name} barks!`; } // Overrides parent method
}
Best Practices & Common Pitfalls
| Pitfall | Best Practice |
|---|---|
Forgetting super() in derived constructor | Always call super() first in child class constructors |
| Naming getters/setters identical to properties | Use _property internally to prevent infinite recursion |
| Treating classes like functions | Classes are not hoisted; define before use |
| Overusing deep inheritance chains | Prefer composition when relationships aren't strict is-a |
Quick Guide
// 🔹 Basic Class
class Product {
constructor(id, name) { this.id = id; this.name = name; }
getInfo() { return `${this.id}: ${this.name}`; }
}
// 🔹 Getters & Setters
class User {
constructor(age) { this._age = age; }
get age() { return this._age; }
set age(val) { if(val >= 0) this._age = val; }
}
// 🔹 Inheritance
class Student extends User {
constructor(age, grade) { super(age); this.grade = grade; }
status() { return `${this.age}yo, Grade ${this.grade}`; }
}
Question 1
Problem Statement
Let us assume you need to organize a library of some electronic manuals and novels for a particular company. For each book, you need to store following information:
- The title
- The author
- The copyright date
- The ISBN
- The number of pages
- The number of times the book has been checked out.
- Whether the book has been discarded
Company wants to perform certain actions when the any book is outdated. The manual books must be exited after 5 years while a novel book should be exited if its checked out time crossed 100.
Task 1.Construct three classes that hold the information needed by company. One class should be a Book class and two child classes of the Book class called Manual and Novel. Each class will contain two methods. One will be a constructor. The other one will either be in charge of disposal of the book or updating the property related to the number of times a book has been checked out.
Task 2: Create an object of the Novel class and Manual class with some valid details.
Task 3: Write the method to count the duration of a manual book and checkout time for novel book so that they can be discarded based on the duration.
Requirements
- Create
Bookbase class +Manual&Novelchild classes - Store: title, author, copyright date, ISBN, pages, checkout count, discarded status
- Manual: discard if age > 5 years
- Novel: discard if checkouts > 100
- Each class: 1 constructor + 1 method (disposal or checkout update)
- Create objects & implement duration/checkout tracking
Demo
📖 Library Book Management
Code
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Session 8 Ex1: Library System</title>
<style>
body {
font-family: sans-serif;
padding: 20px;
max-width: 700px;
margin: auto;
}
.card {
background: #f9f9f9;
padding: 15px;
margin-bottom: 10px;
border-radius: 5px;
border-left: 4px solid #0056b3;
}
</style>
</head>
<body>
<h2>📖 Library Book Management</h2>
<div id="output"></div>
<script>
// Task 1: Base Class
class Book {
constructor(title, author, copyrightDate, ISBN, pages) {
this.title = title;
this.author = author;
this.copyrightDate = copyrightDate;
this.ISBN = ISBN;
this.pages = pages;
this.checkoutCount = 0;
this.discarded = false;
}
}
// Manual Child Class (Discard after 5 years)
class Manual extends Book {
constructor(title, author, copyrightDate, ISBN, pages) {
super(title, author, copyrightDate, ISBN, pages);
}
checkAndDiscardByAge() {
const currentYear = new Date().getFullYear();
const age = currentYear - this.copyrightDate;
if (age > 5) this.discarded = true;
return { age, discarded: this.discarded };
}
}
// Novel Child Class (Discard after 100 checkouts)
class Novel extends Book {
constructor(title, author, copyrightDate, ISBN, pages) {
super(title, author, copyrightDate, ISBN, pages);
}
updateCheckoutAndCheck() {
this.checkoutCount++;
if (this.checkoutCount > 100) this.discarded = true;
return {
count: this.checkoutCount,
discarded: this.discarded,
};
}
}
// Task 2 & 3: Instantiate & Test
const manual1 = new Manual(
"C++ Programming",
"Bjarne Stroustrup",
2018,
"978-0321563842",
1300,
);
const novel1 = new Novel(
"1984",
"George Orwell",
1949,
"978-0451524935",
328,
);
const mStatus = manual1.checkAndDiscardByAge();
for (let i = 0; i < 101; i++) novel1.updateCheckoutAndCheck();
const nStatus = {
count: novel1.checkoutCount,
discarded: novel1.discarded,
};
// Display Results
document.getElementById("output").innerHTML = `
<div class="card">
<strong>📘 Manual:</strong> "${manual1.title}"<br>
Age: ${mStatus.age} years | Checkouts: ${manual1.checkoutCount}<br>
Status: <span style="color:${mStatus.discarded ? "red" : "green"}">${mStatus.discarded ? "❌ Discarded (Outdated)" : "✅ Active"}</span>
</div>
<div class="card">
<strong>📗 Novel:</strong> "${novel1.title}"<br>
Checkouts: ${nStatus.count} | Max Allowed: 100<br>
Status: <span style="color:${nStatus.discarded ? "red" : "green"}">${nStatus.discarded ? "❌ Discarded (Overused)" : "✅ Active"}</span>
</div>
`;
</script>
</body>
</html>
HTML View
Question 2
Problem Statement
Create a product with properties: ID, Name, Description and Price. The create function for this object called displayProductDetails(). This function when invoked should display the name, description and discounted price of the product. For the calculation of discounted price you need to create another function CalculateDisc(percentage). The discount percentage would be given by user.
Requirements
- Create
productobject with: ID, Name, Description, Price - Method
displayProductDetails()→ shows name, description, discounted price - Method
CalculateDisc(percentage)→ computes discounted price - Discount percentage provided by user
Demo
Product Discount Calculator
Code
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Session 8 Ex2: Product Discount</title>
<style>
body {
font-family: sans-serif;
padding: 20px;
max-width: 500px;
margin: auto;
}
input,
button {
padding: 10px;
margin: 5px;
width: 100%;
box-sizing: border-box;
}
pre {
background: #f4f4f4;
padding: 15px;
border-radius: 5px;
white-space: pre-wrap;
}
</style>
</head>
<body>
<h2>Product Discount Calculator</h2>
<input
id="discPercent"
type="number"
placeholder="Enter Discount % (e.g., 20)"
/>
<button id="calcBtn">Calculate & Display Details</button>
<pre id="output">Waiting for input...</pre>
<script>
// Lab Requirement: Object with properties & methods
const product = {
id: "P1001",
name: "Wireless Mechanical Keyboard",
description: "RGB backlit, USB-C charging, Blue switches",
price: 149.99,
CalculateDisc: function (percentage) {
return this.price - this.price * (percentage / 100);
},
displayProductDetails: function (percentage) {
const discPrice = this.CalculateDisc(percentage);
return `📦 Name: ${this.name}\n📝 Description: ${this.description}\n💰 Original Price: $${this.price}\n🏷️ Discounted Price: $${discPrice.toFixed(2)}`;
},
};
document.getElementById("calcBtn").addEventListener("click", () => {
const percent =
parseFloat(document.getElementById("discPercent").value) ||
0;
document.getElementById("output").textContent =
product.displayProductDetails(percent);
});
</script>
</body>
</html>