👶 Understanding Inheritance with Extends
The extends keyword allows one class to inherit from another — this is called subclassing.
This means the child class automatically gets access to the parent class’s:
properties (via constructor using
super)methods (from parent’s prototype)
getters/setters
static methods (if parent has them)
<div class="infographic-jsextends">
<style>
.infographic-jsextends {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--line: #ddd6c9;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--ok: #1a7f4e;
--ok-soft: #e3f5ec;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
--mono-font: 'IBM Plex Mono', 'Courier New', monospace;
margin: 0 auto;
box-sizing: border-box;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-jsextends[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--line: #2c313d;
--accent: #5b8def;
--accent-soft:#202942;
--ok: #5cd6a0;
--ok-soft: #16342a;
}
.infographic-jsextends * { box-sizing: border-box; }
.infographic-jsextends .ig-inner { padding: 1.75rem clamp(1.25rem, 5vw, 3rem) 2rem; }
.infographic-jsextends .ig-title {
font-family: var(--display-font); font-size: clamp(1.4rem, 4.5vw, 1.9rem);
font-weight: 600; text-align: center; margin: 0 0 1.5rem;
}
.infographic-jsextends .card {
border: 2px solid var(--accent); background: var(--accent-soft); border-radius: 10px; padding: 0.9rem 1rem;
}
.infographic-jsextends .card-title { font-family: var(--mono-font); font-size: 0.85rem; font-weight: 700; text-align: center; color: var(--accent); margin-bottom: 0.5rem; }
.infographic-jsextends .member-list { display: flex; flex-wrap: wrap; gap: 0.4rem; justify-content: center; }
.infographic-jsextends .member-tag {
font-family: var(--mono-font); font-size: 0.72rem; font-weight: 700; padding: 0.25rem 0.55rem; border-radius: 5px;
border: 1px solid var(--accent); color: var(--accent); background: var(--paper);
}
.infographic-jsextends .link-row { display: flex; flex-direction: column; align-items: center; margin: 0.3rem 0; }
.infographic-jsextends .link-arrow { font-size: 1.1rem; color: var(--ink-soft); }
.infographic-jsextends .link-label { font-family: var(--mono-font); font-size: 0.7rem; color: var(--ink-soft); }
.infographic-jsextends .child-card {
border: 2px solid var(--ok); background: var(--ok-soft); border-radius: 10px; padding: 0.9rem 1rem;
}
.infographic-jsextends .child-card .card-title { color: var(--ok); }
.infographic-jsextends .child-card .card-title .super { color: var(--ink-soft); font-weight: 400; }
.infographic-jsextends .child-card .member-tag { border-color: var(--ok); color: var(--ok); }
.infographic-jsextends .reveal-row { display: flex; justify-content: center; margin: 1.5rem 0; }
.infographic-jsextends .reveal-btn {
font: inherit; font-size: 0.85rem; font-weight: 700; border: none; background: var(--ink);
color: var(--paper); padding: 0.6rem 1.3rem; border-radius: 999px; cursor: pointer;
}
.infographic-jsextends .reveal-btn:hover { opacity: 0.88; }
.infographic-jsextends .instance-card {
border: 2px dashed var(--line); border-radius: 10px; padding: 0.9rem 1rem; min-height: 3rem;
}
.infographic-jsextends .instance-title { font-family: var(--mono-font); font-size: 0.8rem; text-align: center; color: var(--ink-soft); margin-bottom: 0.6rem; }
.infographic-jsextends .instance-list { display: flex; flex-wrap: wrap; gap: 0.4rem; justify-content: center; }
.infographic-jsextends .inst-tag {
font-family: var(--mono-font); font-size: 0.75rem; font-weight: 700; padding: 0.28rem 0.6rem; border-radius: 5px;
opacity: 0; transform: scale(0.7); transition: opacity 0.3s ease, transform 0.3s ease;
}
.infographic-jsextends .inst-tag.is-in { opacity: 1; transform: scale(1); }
.infographic-jsextends .inst-tag.inherited { border: 1px solid var(--accent); color: var(--accent); background: var(--accent-soft); }
.infographic-jsextends .inst-tag.own { border: 1px solid var(--ok); color: var(--ok); background: var(--ok-soft); }
.infographic-jsextends .key-row { display: flex; gap: 1.25rem; justify-content: center; margin-top: 0.9rem; }
.infographic-jsextends .key-item { display: flex; align-items: center; gap: 0.35rem; font-size: 0.72rem; color: var(--ink-soft); }
.infographic-jsextends .swatch { width: 0.7rem; height: 0.7rem; border-radius: 3px; }
.infographic-jsextends .swatch.inherited { background: var(--accent); }
.infographic-jsextends .swatch.own { background: var(--ok); }
@media (prefers-reduced-motion: reduce) {
.infographic-jsextends *, .infographic-jsextends *::before, .infographic-jsextends *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ig-inner">
<h2 class="ig-title">Inheritance with extends</h2>
<div class="card">
<div class="card-title">class Animal</div>
<div class="member-list">
<span class="member-tag">name</span>
<span class="member-tag">speak()</span>
<span class="member-tag">get label</span>
<span class="member-tag">static info()</span>
</div>
</div>
<div class="link-row">
<span class="link-arrow">↑</span>
<span class="link-label">extends</span>
</div>
<div class="child-card">
<div class="card-title">class Dog <span class="super">extends Animal</span></div>
<div class="member-list">
<span class="member-tag">bark()</span>
</div>
</div>
<div class="reveal-row">
<button class="reveal-btn" id="revealBtn">What can a Dog do?</button>
</div>
<div class="instance-card">
<div class="instance-title">new Dog()</div>
<div class="instance-list" id="instanceList"></div>
</div>
<div class="key-row">
<span class="key-item"><span class="swatch inherited"></span>inherited from Animal</span>
<span class="key-item"><span class="swatch own"></span>Dog's own</span>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-jsextends')
|| document.querySelector('.infographic-jsextends');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const revealBtn = wrapper.querySelector('#revealBtn');
const instanceList = wrapper.querySelector('#instanceList');
const MEMBERS = [
{ label: 'name', type: 'inherited' },
{ label: 'speak()', type: 'inherited' },
{ label: 'get label', type: 'inherited' },
{ label: 'static info()', type: 'inherited' },
{ label: 'bark()', type: 'own' }
];
let revealed = false;
function reveal() {
instanceList.innerHTML = '';
MEMBERS.forEach(m => {
const tag = document.createElement('span');
tag.className = `inst-tag ${m.type}`;
tag.textContent = m.label;
instanceList.appendChild(tag);
requestAnimationFrame(() => tag.classList.add('is-in'));
});
revealed = true;
revealBtn.textContent = 'Hide';
}
function hide() {
instanceList.innerHTML = '';
revealed = false;
revealBtn.textContent = 'What can a Dog do?';
}
revealBtn.addEventListener('click', () => revealed ? hide() : reveal());
})();
</script>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});Syntax:
class ChildClass extends ParentClass {
constructor(args) {
super(args); // calls parent class constructor
// child-specific properties
}
childMethod() {
// method specific to ChildClass
}
}Example:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // must call super() before using 'this'
this.breed = breed;
}
showBreed() {
console.log(`Breed is ${this.breed}`)
}
}
const myDog = new Dog("Rocky", "Labrador");
myDog.speak(); // Output: Rocky makes a noise.
myDog.showBreed(); // Output: Breed is Labrador🧾 Explanation:
class Dog extends Animal→ Dog inherits from Animal, meaning Dog.prototype is linked to Animal.prototype.
super(name)→ calls the parent class constructor (Animal’s constructor) and assigns
this.name = name.It must be called before using
thisin a subclass.myDog→ has access to:
name(from Animal constructor)breed(from Dog constructor)speak()(from Animal.prototype)showBreed()(from Dog.prototype)
✅ Why do we need super(name) in Child Class Dog?
1) To run the parent constructor
Animal has:
constructor(name) {
this.name = name;
}So super(name) does:
✔ call Animal's constructor
✔ sets this.name = "Rocky" for the Dog object
Without it, the Dog will not get the name.
2) JavaScript requires it BEFORE using this
In a class that uses extends:
You cannot access
thisuntilsuper()is called
constructor(name, breed) {
this.breed = breed; // ❌ ERROR: Must call super()
}This will throw:
ReferenceError: Must call super constructor before accessing 'this'Because:
✅ super() creates and initializes this
❌ Without it, this does not exist yet
3) It sets up inheritance correctly
super() ensures:
the object is linked to the parent prototype
inherited methods work
So after calling super():
myDog.speak(); // works because Dog inherits Animal methods