JavaScript 30 🧬 Classes
A class is a blueprint for creating objects. It encapsulates data (properties) and functions (methods) that operate on the data. Classes provide a clean, modern syntax for object-oriented programming in JavaScript.
A Quick Look at the Example
class MyClass {
// Class field (property with default value)
myProperty = "default value";
// Constructor — initializes the object
constructor(param1, param2) {
this.property1 = param1;
this.property2 = param2;
}
// Method — a function that operates on the data
myMethod() {
console.log(this.property1, this.property2, this.myProperty);
}
}
// Inheritance — SubClass extends MyClass
class SubClass extends MyClass {}
// Creating an instance
const obj = new MyClass("value1", "value2");
obj.myMethod(); // "value1 value2 default value"
a. Classes — Part 1
A class is a blueprint for creating objects. It encapsulates data (properties) and functions (methods) that operate on the data.
Class Declaration
You declare a class using the class keyword followed by the name of the class. The class body is enclosed in curly braces { }.
class MyClass {
// class body
}
Key points:
- Class names are typically PascalCase (e.g.,
MyClass,Person,BankAccount) - Classes are not hoisted — you must define them before using them
- Classes are first-class citizens — you can pass them as arguments, return them, assign them to variables
Constructor Method
A special method named constructor() is used to initialize objects created from a class.
- It’s called automatically when an object is instantiated using the
newkeyword - If you don’t provide your own constructor, JavaScript uses a default one
- You can only have one constructor per class
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const person = new Person("Alice", 30);
console.log(person.name); // "Alice"
console.log(person.age); // 30
Default constructor:
class Empty {
// No constructor — JavaScript provides a default one
}
const obj = new Empty();
// Equivalent to: constructor() {}
Properties
Classes can have properties — variables that store data for individual objects. They can be defined:
| Method | Description | Example |
|---|---|---|
| In constructor | Assigned to this | this.name = name; |
| Class fields | Defined in class body | myProperty = "default value"; |
class MyClass {
// Class field (ES2022)
myProperty = "default value";
// Constructor — instance properties
constructor(param1, param2) {
this.property1 = param1;
this.property2 = param2;
}
}
const obj = new MyClass("value1", "value2");
console.log(obj.myProperty); // "default value"
console.log(obj.property1); // "value1"
console.log(obj.property2); // "value2"
Class fields vs constructor properties:
| Aspect | Class Fields | Constructor |
|---|---|---|
| Syntax | prop = value; | this.prop = value; |
| When set | Before constructor body runs | In constructor body |
| Parameters | Cannot use constructor params | Can use parameters |
| Use case | Defaults, private fields | Computed values, params |
b. Classes — Part 2
Methods
Classes can have methods — functions defined within the class. These methods manipulate object properties and perform actions.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
// Method
greet() {
return `Hello, my name is ${this.name}`;
}
// Method with parameters
celebrateBirthday() {
this.age++;
return `Happy birthday! Now ${this.age}.`;
}
}
const person = new Person("Alice", 30);
console.log(person.greet()); // "Hello, my name is Alice"
console.log(person.celebrateBirthday()); // "Happy birthday! Now 31."
Key points:
- Methods are defined inside the class body but outside the constructor
- Methods are shared across all instances (stored on the prototype)
- No need for
functionkeyword - No commas between methods
Inheritance
JavaScript supports inheritance — creating a new class that inherits properties and methods from an existing class (the parent or base class).
Use the extends keyword:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound.`;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // Call parent constructor
this.breed = breed;
}
bark() {
return `${this.name} barks!`;
}
// Override parent method
speak() {
return `${this.name} barks.`;
}
}
const dog = new Dog("Rex", "Labrador");
console.log(dog.speak()); // "Rex barks." (overridden)
console.log(dog.bark()); // "Rex barks!" (own method)
console.log(dog.name); // "Rex" (inherited property)
console.log(dog.breed); // "Labrador" (own property)
The super keyword:
| Usage | Description |
|---|---|
super(args) | Calls the parent constructor |
super.method() | Calls a parent method |
Important rules:
super()must be called before accessingthisin a subclass constructor- If the parent has a constructor, the subclass must call
super() - Method overriding — a subclass can redefine a parent’s method
Object Creation
After defining a class, you create objects (instances) using the new keyword. This calls the constructor method to initialize the new object with the provided arguments.
class Person {
constructor(name) {
this.name = name;
}
}
const person = new Person("Alice");
What happens with new:
- A new empty object is created
- The constructor is called with the given arguments
thisrefers to the new object- The new object is returned (unless constructor returns another object)
Complete Example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Classes</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #f8f9fa;
color: #333;
line-height: 1.6;
}
h1 { color: #007bff; border-bottom: 3px solid #007bff; padding-bottom: 10px; }
h2 { color: #28a745; border-left: 4px solid #28a745; padding-left: 15px; margin-top: 30px; }
.demo-box {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
margin: 15px 0;
}
pre {
background: #1e1e1e;
color: #d4d4d4;
padding: 15px;
border-radius: 8px;
overflow-x: auto;
font-family: 'Courier New', monospace;
font-size: 0.9rem;
line-height: 1.8;
}
.keyword { color: #569cd6; }
.string { color: #ce9178; }
.number { color: #b5cea8; }
.function { color: #dcdcaa; }
.comment { color: #6a9955; }
.boolean { color: #569cd6; }
.class-name { color: #4ec9b0; }
#output {
background: #e9ecef;
padding: 15px;
border-radius: 8px;
margin-top: 15px;
min-height: 40px;
font-family: 'Courier New', monospace;
font-size: 0.85rem;
border-left: 4px solid #007bff;
white-space: pre-wrap;
}
table {
width: 100%;
border-collapse: collapse;
margin: 15px 0;
}
th, td {
padding: 10px;
border: 1px solid #ddd;
text-align: left;
}
th { background: #007bff; color: white; }
tr:nth-child(even) { background: #f8f9fa; }
.btn {
padding: 10px 20px;
background: #007bff;
color: white;
border: none;
border-radius: 6px;
font-size: 1em;
font-weight: bold;
cursor: pointer;
margin: 5px;
transition: all 0.3s;
}
.btn:hover {
background: #0056b3;
transform: translateY(-2px);
}
.btn-success { background: #28a745; }
.btn-success:hover { background: #1e7e34; }
.btn-danger { background: #dc3545; }
.btn-danger:hover { background: #a71d2a; }
.class-display {
font-family: 'Courier New', monospace;
font-size: 1.05em;
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
margin: 10px 0;
border-left: 4px solid #007bff;
white-space: pre-wrap;
line-height: 1.8;
}
.input-group {
margin: 10px 0;
}
.input-group label {
display: inline-block;
min-width: 150px;
font-weight: bold;
}
.input-group input {
padding: 8px 12px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 1em;
width: 200px;
}
.input-group input:focus {
outline: none;
border-color: #007bff;
}
.hierarchy {
font-family: 'Courier New', monospace;
font-size: 0.85rem;
background: #1e1e1e;
color: #d4d4d4;
padding: 20px;
border-radius: 8px;
margin: 15px 0;
white-space: pre;
overflow-x: auto;
line-height: 1.8;
}
</style>
</head>
<body>
<h1>Classes</h1>
<div class="demo-box">
<h2>1. Basic Class</h2>
<pre>
<span class="keyword">class</span> <span class="class-name">MyClass</span> {
<span class="comment">// Class field (ES2022)</span>
myProperty = <span class="string">"default value"</span>;
<span class="comment">// Constructor</span>
<span class="function">constructor</span>(param1, param2) {
<span class="keyword">this</span>.property1 = param1;
<span class="keyword">this</span>.property2 = param2;
}
<span class="comment">// Method</span>
<span class="function">myMethod</span>() {
console.log(<span class="keyword">this</span>.property1, <span class="keyword">this</span>.property2, <span class="keyword">this</span>.myProperty);
}
}
<span class="keyword">const</span> obj = <span class="keyword">new</span> <span class="class-name">MyClass</span>(<span class="string">"value1"</span>, <span class="string">"value2"</span>);
obj.<span class="function">myMethod</span>(); <span class="comment">// "value1 value2 default value"</span>
</pre>
</div>
<div class="demo-box">
<h2>2. Inheritance with extends and super</h2>
<pre>
<span class="keyword">class</span> <span class="class-name">Animal</span> {
<span class="function">constructor</span>(name) {
<span class="keyword">this</span>.name = name;
}
<span class="function">speak</span>() {
<span class="keyword">return</span> <span class="string">`${this.name} makes a sound.`</span>;
}
}
<span class="keyword">class</span> <span class="class-name">Dog</span> <span class="keyword">extends</span> <span class="class-name">Animal</span> {
<span class="function">constructor</span>(name, breed) {
<span class="keyword">super</span>(name); <span class="comment">// Call parent constructor</span>
<span class="keyword">this</span>.breed = breed;
}
<span class="function">bark</span>() {
<span class="keyword">return</span> <span class="string">`${this.name} barks!`</span>;
}
<span class="comment">// Override parent method</span>
<span class="function">speak</span>() {
<span class="keyword">return</span> <span class="string">`${this.name} barks.`</span>;
}
}
</pre>
</div>
<div class="demo-box">
<h2>3. Class Hierarchy Visualization</h2>
<div class="hierarchy">
<span style="color: #4ec9b0;">Animal</span> (parent class)
├── constructor(name)
├── speak()
│
└── <span style="color: #4ec9b0;">Dog</span> (child class, extends Animal)
├── constructor(name, breed)
│ └── super(name) ← calls Animal's constructor
├── bark() ← own method
└── speak() ← overridden method
</div>
</div>
<div class="demo-box">
<h2>4. Class Syntax Reference</h2>
<table>
<tr>
<th>Feature</th>
<th>Syntax</th>
<th>Example</th>
</tr>
<tr>
<td><strong>Declaration</strong></td>
<td><code>class Name { }</code></td>
<td><code>class Person { }</code></td>
</tr>
<tr>
<td><strong>Constructor</strong></td>
<td><code>constructor(params) { }</code></td>
<td><code>constructor(name) { this.name = name; }</code></td>
</tr>
<tr>
<td><strong>Class field</strong></td>
<td><code>prop = value;</code></td>
<td><code>age = 0;</code></td>
</tr>
<tr>
<td><strong>Method</strong></td>
<td><code>name() { }</code></td>
<td><code>greet() { return "Hi"; }</code></td>
</tr>
<tr>
<td><strong>Getter</strong></td>
<td><code>get name() { }</code></td>
<td><code>get fullName() { return ...; }</code></td>
</tr>
<tr>
<td><strong>Setter</strong></td>
<td><code>set name(v) { }</code></td>
<td><code>set age(v) { this._age = v; }</code></td>
</tr>
<tr>
<td><strong>Static method</strong></td>
<td><code>static name() { }</code></td>
<td><code>static create() { return new Person(); }</code></td>
</tr>
<tr>
<td><strong>Private field</strong></td>
<td><code>#name;</code></td>
<td><code>#balance = 0;</code></td>
</tr>
<tr>
<td><strong>Inheritance</strong></td>
<td><code>class B extends A { }</code></td>
<td><code>class Dog extends Animal { }</code></td>
</tr>
<tr>
<td><strong>Parent call</strong></td>
<td><code>super(args)</code></td>
<td><code>super(name)</code></td>
</tr>
</table>
</div>
<div class="demo-box">
<h2>5. Interactive: Class Playground</h2>
<div class="input-group">
<label for="nameInput">Name:</label>
<input type="text" id="nameInput" value="Alice">
</div>
<div class="input-group">
<label for="ageInput">Age:</label>
<input type="number" id="ageInput" value="30">
</div>
<div style="margin: 10px 0;">
<button class="btn btn-success" onclick="createPerson()">Create Person</button>
<button class="btn" onclick="createDog()">Create Dog</button>
<button class="btn" onclick="showHierarchy()">Show Hierarchy</button>
<button class="btn btn-danger" onclick="clearOutput()">Clear</button>
</div>
<div class="class-display" id="classDisplay">Create an object to see its details</div>
</div>
<div class="demo-box">
<h2>6. Live Output — All Examples</h2>
<div id="output">Loading...</div>
</div>
<script>
// ============================================
// Classes — Live Demo
// ============================================
let results = [];
// 1. Basic class
results.push('📌 Basic Class:\n');
class MyClass {
myProperty = "default value";
constructor(param1, param2) {
this.property1 = param1;
this.property2 = param2;
}
myMethod() {
return `${this.property1} ${this.property2} ${this.myProperty}`;
}
}
const obj = new MyClass("value1", "value2");
results.push(' const obj = new MyClass("value1", "value2")');
results.push(' obj.myMethod() → "' + obj.myMethod() + '"');
results.push('');
// 2. Constructor + properties
results.push('📌 Constructor and Properties:\n');
class Person {
species = "Homo sapiens"; // Class field
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, my name is ${this.name}`;
}
celebrateBirthday() {
this.age++;
return `Happy birthday! Now ${this.age}.`;
}
}
const alice = new Person("Alice", 30);
results.push(' const alice = new Person("Alice", 30)');
results.push(' alice.name → "' + alice.name + '"');
results.push(' alice.age → ' + alice.age);
results.push(' alice.species → "' + alice.species + '" (class field)');
results.push(' alice.greet() → "' + alice.greet() + '"');
results.push(' alice.celebrateBirthday() → "' + alice.celebrateBirthday() + '"');
results.push('');
// 3. Inheritance
results.push('📌 Inheritance:\n');
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound.`;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
bark() {
return `${this.name} barks!`;
}
speak() {
return `${this.name} barks.`;
}
}
const dog = new Dog("Rex", "Labrador");
results.push(' const dog = new Dog("Rex", "Labrador")');
results.push(' dog.name → "' + dog.name + '" (inherited)');
results.push(' dog.breed → "' + dog.breed + '" (own)');
results.push(' dog.speak() → "' + dog.speak() + '" (overridden)');
results.push(' dog.bark() → "' + dog.bark() + '" (own)');
results.push(' dog instanceof Dog → ' + (dog instanceof Dog));
results.push(' dog instanceof Animal → ' + (dog instanceof Animal));
results.push('');
// 4. Multi-level inheritance
results.push('📌 Multi-Level Inheritance:\n');
class Vehicle {
constructor(brand) {
this.brand = brand;
}
start() { return `${this.brand} starts.`; }
}
class Car extends Vehicle {
constructor(brand, model) {
super(brand);
this.model = model;
}
drive() { return `${this.brand} ${this.model} drives.`; }
}
class ElectricCar extends Car {
constructor(brand, model, range) {
super(brand, model);
this.range = range;
}
charge() { return `Charging... ${this.range}km range.`; }
}
const tesla = new ElectricCar("Tesla", "Model 3", 500);
results.push(' const tesla = new ElectricCar("Tesla", "Model 3", 500)');
results.push(' tesla.start() → "' + tesla.start() + '" (from Vehicle)');
results.push(' tesla.drive() → "' + tesla.drive() + '" (from Car)');
results.push(' tesla.charge() → "' + tesla.charge() + '" (own)');
results.push(' tesla instanceof Vehicle → ' + (tesla instanceof Vehicle));
results.push(' tesla instanceof Car → ' + (tesla instanceof Car));
results.push(' tesla instanceof ElectricCar → ' + (tesla instanceof ElectricCar));
results.push('');
// 5. Static methods
results.push('📌 Static Methods:\n');
class MathHelper {
static add(a, b) {
return a + b;
}
static multiply(a, b) {
return a * b;
}
}
results.push(' MathHelper.add(5, 3) → ' + MathHelper.add(5, 3));
results.push(' MathHelper.multiply(4, 7) → ' + MathHelper.multiply(4, 7));
results.push(' → Static methods are called on the CLASS, not instances');
results.push('');
// 6. Getters and setters
results.push('📌 Getters and Setters:\n');
class Temperature {
constructor(celsius) {
this._celsius = celsius;
}
get celsius() {
return this._celsius;
}
set celsius(value) {
if (value < -273.15) throw new Error("Below absolute zero!");
this._celsius = value;
}
get fahrenheit() {
return this._celsius * 9 / 5 + 32;
}
set fahrenheit(value) {
this._celsius = (value - 32) * 5 / 9;
}
}
const temp = new Temperature(25);
results.push(' const temp = new Temperature(25)');
results.push(' temp.celsius → ' + temp.celsius);
results.push(' temp.fahrenheit → ' + temp.fahrenheit);
temp.fahrenheit = 100;
results.push(' After temp.fahrenheit = 100:');
results.push(' temp.celsius → ' + temp.celsius.toFixed(2));
results.push('');
// 7. Private fields
results.push('📌 Private Fields (#):\n');
class BankAccount {
#balance = 0;
constructor(initialBalance) {
this.#balance = initialBalance;
}
deposit(amount) {
if (amount < 0) throw new Error("Cannot deposit negative");
this.#balance += amount;
return this.#balance;
}
getBalance() {
return this.#balance;
}
}
const account = new BankAccount(1000);
account.deposit(500);
results.push(' const account = new BankAccount(1000)');
results.push(' account.deposit(500)');
results.push(' account.getBalance() → ' + account.getBalance());
results.push(' → #balance is private — cannot access from outside');
results.push('');
// 8. Classes vs Prototypes
results.push('📌 Classes vs Prototypes:\n');
results.push(' → Classes are syntactic sugar over prototypes');
results.push(' → class Person { } is equivalent to function Person() { }');
results.push(' → Methods defined in classes go on the prototype');
results.push('');
// 9. Practical: Task class
results.push('📌 Practical: Task Manager:\n');
class Task {
static nextId = 1;
constructor(title) {
this.id = Task.nextId++;
this.title = title;
this.completed = false;
this.createdAt = new Date();
}
complete() {
this.completed = true;
return `✅ Task "${this.title}" completed`;
}
toString() {
const status = this.completed ? '✅' : '⬜';
return `${status} [${this.id}] ${this.title}`;
}
}
const task1 = new Task("Learn JavaScript");
const task2 = new Task("Build a project");
results.push(' ' + task1.toString());
results.push(' ' + task2.toString());
results.push(' ' + task1.complete());
results.push(' ' + task1.toString());
results.push('');
// 10. Practical: Shapes
results.push('📌 Practical: Shape Hierarchy:\n');
class Shape {
constructor(name) {
this.name = name;
}
area() {
return 0;
}
toString() {
return `${this.name}: area = ${this.area().toFixed(2)}`;
}
}
class Circle extends Shape {
constructor(radius) {
super("Circle");
this.radius = radius;
}
area() {
return Math.PI * this.radius ** 2;
}
}
class Rectangle extends Shape {
constructor(width, height) {
super("Rectangle");
this.width = width;
this.height = height;
}
area() {
return this.width * this.height;
}
}
const circle = new Circle(5);
const rect = new Rectangle(4, 6);
results.push(' ' + circle.toString());
results.push(' ' + rect.toString());
results.push(' → Polymorphism: same method, different behavior!');
document.getElementById('output').textContent = results.join('\n');
// ============================================
// Interactive: Class Playground
// ============================================
class InteractivePerson {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, I'm ${this.name}, ${this.age} years old.`;
}
isAdult() {
return this.age >= 18;
}
}
class InteractiveDog {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} says Woof!`;
}
}
function createPerson() {
const name = document.getElementById('nameInput').value;
const age = Number(document.getElementById('ageInput').value);
const person = new InteractivePerson(name, age);
const display = document.getElementById('classDisplay');
display.textContent =
`👤 InteractivePerson\n` +
`─────────────────────\n` +
`name: "${person.name}"\n` +
`age: ${person.age}\n` +
`greet(): "${person.greet()}"\n` +
`isAdult(): ${person.isAdult()}\n` +
`\n` +
`instanceof InteractivePerson: ${person instanceof InteractivePerson}`;
}
function createDog() {
const name = document.getElementById('nameInput').value;
const dog = new InteractiveDog(name);
const display = document.getElementById('classDisplay');
display.textContent =
`🐕 InteractiveDog\n` +
`─────────────────────\n` +
`name: "${dog.name}"\n` +
`speak(): "${dog.speak()}"\n` +
`\n` +
`instanceof InteractiveDog: ${dog instanceof InteractiveDog}\n` +
`instanceof InteractivePerson: ${dog instanceof InteractivePerson}`;
}
function showHierarchy() {
const display = document.getElementById('classDisplay');
display.textContent =
`📊 Class Hierarchy\n` +
`─────────────────────\n` +
`\n` +
` Animal\n` +
` / \\\n` +
` Dog Cat\n` +
` |\n` +
` Puppy\n` +
`\n` +
`Each level inherits from its parent.\n` +
`Methods can be overridden at each level.`;
}
function clearOutput() {
document.getElementById('classDisplay').textContent = 'Create an object to see its details';
}
</script>
</body>
</html>
Quick Reference
Class Syntax
| Feature | Syntax | Example |
|---|---|---|
| Declaration | class Name { } | class Person { } |
| Constructor | constructor(params) { } | constructor(name) { this.name = name; } |
| Class field | prop = value; | age = 0; |
| Method | name() { } | greet() { return "Hi"; } |
| Getter | get name() { } | get fullName() { ... } |
| Setter | set name(v) { } | set age(v) { ... } |
| Static method | static name() { } | static create() { } |
| Private field | #name; | #balance = 0; |
| Inheritance | class B extends A { } | class Dog extends Animal { } |
| Parent call | super(args) | super(name) |
Key Concepts
| Concept | Description |
|---|---|
| Class | Blueprint for creating objects |
| Constructor | Special method for initialization |
| Instance | Object created from a class |
| Inheritance | Child class inherits from parent |
| Override | Child replaces parent’s method |
super | Reference to parent class |
| Static | Belongs to class, not instances |
Private (#) | Only accessible inside the class |
Constructor Rules
| Rule | Description |
|---|---|
| One per class | Can only have one constructor |
| Auto-called | Called automatically by new |
Must call super() | In subclass before using this |
| Optional | Default constructor used if omitted |
| Return value | Returns this by default |
Best Practices
✅ Do This:
// Use PascalCase for class names
class Person { }
// Call super() in subclass constructors
class Dog extends Animal {
constructor(name) {
super(name);
this.breed = breed;
}
}
// Use private fields for internal state
class BankAccount {
#balance = 0;
}
// Use static methods for utility functions
class MathUtil {
static add(a, b) { return a + b; }
}
// Use getters for computed properties
class Circle {
get area() { return Math.PI * this.radius ** 2; }
}
// Keep classes focused on one responsibility
class UserService { }
class UserRepository { }
❌ Don’t Do This:
// Don't forget super() in subclass
class Dog extends Animal {
constructor(name) {
this.name = name; // ❌ ReferenceError before super()
}
}
// Don't use classes when plain objects work
class Point {
constructor(x, y) { this.x = x; this.y = y; }
}
// Simpler: const point = { x: 1, y: 2 };
// Don't overuse inheritance
class FlyingSwimmingWalkingAnimal { } // ❌ Prefer composition
// Don't forget `new` when instantiating
const p = Person("Alice"); // ❌ TypeError: Cannot call class without new
// Don't use classes for singletons
class Config { } // ⚠️ Use a plain object for singletons
// Don't expose mutable state directly
class BadPerson {
constructor() {
this.address = {}; // ❌ Anyone can mutate
}
}
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
Forgetting new | TypeError | Always use new ClassName() |
Missing super() | ReferenceError | Call super() first in subclass |
| Hoisting | Class not defined yet | Define before using |
| Method binding | this lost in callbacks | Use arrow functions or bind |
| Private field outside class | SyntaxError | Only use # inside class body |
| Overusing inheritance | Rigid hierarchies | Prefer composition |
Classes vs Functions (Prototypes)
// Class (modern)
class Person {
constructor(name) {
this.name = name;
}
greet() {
return `Hi, ${this.name}`;
}
}
// Equivalent (prototype-based)
function PersonOld(name) {
this.name = name;
}
PersonOld.prototype.greet = function() {
return `Hi, ${this.name}`;
};
Both create the same underlying structure — classes are syntactic sugar over prototypes!
Real-World Example
// Custom Error hierarchy
class AppError extends Error {
constructor(message, code) {
super(message);
this.name = 'AppError';
this.code = code;
}
}
class ValidationError extends AppError {
constructor(message, field) {
super(message, 'VALIDATION_ERROR');
this.name = 'ValidationError';
this.field = field;
}
}
class NotFoundError extends AppError {
constructor(resource) {
super(`${resource} not found`, 'NOT_FOUND');
this.name = 'NotFoundError';
}
}
try {
throw new ValidationError('Invalid email', 'email');
} catch (err) {
console.log(err instanceof AppError); // true
console.log(err instanceof ValidationError); // true
console.log(err.code); // "VALIDATION_ERROR"
console.log(err.field); // "email"
}
Pro Tip: Classes provide a clean, modern syntax for object-oriented programming in JavaScript. Use them for:
- Data models (User, Product, Order)
- Services (UserService, ApiClient)
- Custom errors (extending
Error) - UI components (React class components)
Key rules:
- Use PascalCase for class names
- Always call
super()before usingthisin subclasses - Use private fields (
#) for internal state - Use static methods for class-level utilities
- Use getters/setters for computed properties or validation
But remember: Don’t overuse classes! Plain objects and functions often work better for simple cases. Use classes when you need encapsulation, inheritance, or multiple instances of similar objects.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!