Classes and the Prototype Chain
class Course {
constructor(title, lessonCount) {
this.title = title;
this.lessonCount = lessonCount;
}
describe() {
return `${this.title} has ${this.lessonCount} lessons`;
}
}
const jsCourse = new Course("JavaScript", 11);
console.log(jsCourse.describe());
constructor runs automatically whenever you create a new object with new, setting up its starting properties. Every method you define inside the class, like describe(), becomes available on every object created from it.
Inheritance with extends
class CertifiedCourse extends Course {
constructor(title, lessonCount, certificateName) {
super(title, lessonCount);
this.certificateName = certificateName;
}
}
const certified = new CertifiedCourse("JavaScript", 11, "JS Pro");
console.log(certified.describe()); // inherited from Course
extends gives CertifiedCourse everything Course already has, plus its own additional property. super(...) calls the parent class’s constructor so you don’t have to repeat that setup logic yourself.
What’s really happening: prototypes
JavaScript classes are largely syntax sugar over something called the prototype chain — every object has a hidden internal link to another object it inherits methods and properties from. class and extends just make that mechanism far easier to read and write than the manual prototype code JavaScript required before 2015. Understanding it helps once you eventually debug an error like TypeError: x is not a function, which usually means a method doesn’t exist anywhere in an object’s prototype chain.
Static methods
class MathHelper {
static double(n) {
return n * 2;
}
}
console.log(MathHelper.double(5)); // 10 -- called on the class itself, not an instance
A static method belongs to the class itself rather than to individual objects created from it — useful for utility functions that logically relate to the class but don’t need access to any specific instance’s data.