Here's a secret that Professor Semicolon has been dying to tell you.
JavaScript didn't have classes until 2015. Before that, people still did object-oriented programming, using something called prototypes. And here's the twist: classes are mostly just nicer syntax on top of prototypes. Under the hood, they're still prototypes.
Every object in JavaScript has a hidden link to another object, called its prototype. When you ask an object for a property it doesn't have, JavaScript doesn't give up straight away. It follows the link and looks in the prototype. If it's not there, it looks in the prototype's prototype, and so on up the prototype chain, until it finds the property or runs out of prototypes.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound.`;
}
}
const cat = new Animal("Whiskers");
console.log(Object.keys(cat));
console.log(Object.getPrototypeOf(cat) === Animal.prototype);
console.log(Object.getOwnPropertyNames(Animal.prototype));
console.log(typeof Animal);
It prints
[ 'name' ] true [ 'constructor', 'speak' ] function
Look at that! The cat object itself only has one property: name. The speak method isn't stored on the cat at all. It lives on Animal.prototype, which is the cat's prototype. When you call cat.speak(), JavaScript doesn't find speak on cat, follows the link to Animal.prototype, finds it there, and runs it with this set to cat.
This is actually very efficient. If you create a million cats, there's still only one copy of speak, shared by all of them through the prototype. And notice that typeof Animal is "function". A class is really a special kind of function!
This also explains how every array has methods like map and push: they live on Array.prototype, which every array links to. And it's how inheritance works: Wizard.prototype links to Character.prototype, so wizards can find Character methods by following the chain.
You don't need to work with prototypes directly in modern code. Classes are the way to go. But knowing that prototypes exist will help you understand error messages, older code, and documentation (MDN talks about Array.prototype.map, for example, which simply means "the map method that all arrays share").