Let's explore two ways to create methods in JavaScript using Oreo the cat as our example. These approaches affect how your code performs and uses memory.
Two Ways to Create Cat Methods
// Method 1: Instance Methods (using this)
function Cat(name) {
this.name = name;
// Method attached directly to each cat
this.meow = function() {
console.log(`${this.name} says meow!`);
};
}
// Method 2: Prototype Methods
function BetterCat(name) {
this.name = name;
}
// Method attached to the cat blueprint (prototype)
BetterCat.prototype.meow = function() {
console.log(`${this.name} says meow!`);
};
What's the Difference?
Let's create some cats:
// Create two cats using instance methods
const oreo1 = new Cat("Oreo");
const felix1 = new Cat("Felix");
// Create two cats using prototype methods
const oreo2 = new BetterCat("Oreo");
const felix2 = new BetterCat("Felix");
// Are their methods the same?
console.log(oreo1.meow === felix1.meow); // false - each cat has its own copy
console.log(oreo2.meow === felix2.meow); // true - both cats share one method
Memory: The Big Difference
Instance Methods
Each cat gets its own copy of every method:
oreo1: { name: "Oreo", meow: function() {...} }
felix1: { name: "Felix", meow: function() {...} }
whiskers1: { name: "Whiskers", meow: function() {...} }
Prototype Methods
All cats share the same methods:
oreo2: { name: "Oreo" } ─────────────┐
felix2: { name: "Felix" } ───────────┼─→ BetterCat.prototype.meow
whiskers2: { name: "Whiskers" } ─────┘
Why This Matters
If you have many cats (like a cat shelter app with thousands of cats), prototype methods use much less memory:
// Creating 10,000 cats
function createManyCats(count) {
// Instance method cats - each has its own methods
const instanceCats = [];
for (let i = 0; i < count; i++) {
instanceCats.push(new Cat(`Cat${i}`));
}
// Prototype method cats - all share methods
const protoCats = [];
for (let i = 0; i < count; i++) {
protoCats.push(new BetterCat(`Cat${i}`));
}
}
createManyCats(10000);
// The prototype version uses much less memory!
When To Use Each
Use Instance Methods When:
- Each cat needs its own unique version of a method
- You need to remember information from when the cat was created
function SpecialCat(name, favoriteToy) {
this.name = name;
this.play = function() {
console.log(`${this.name} plays with ${favoriteToy}`);
};
}
const oreo = new SpecialCat("Oreo", "feather wand");
oreo.play(); // "Oreo plays with feather wand"
Use Prototype Methods When:
- All cats do the same thing in the same way
- You're creating lots of cats
- You want faster, more efficient code
Modern JavaScript - Classes
The modern way to do this is with classes. Methods in classes automatically use prototypes:
class Cat {
constructor(name) {
this.name = name;
// Instance method - each cat gets its own copy
this.uniqueId = function() {
return Math.random().toString(36).slice(2, 7);
};
}
// Prototype method - all cats share this
meow() {
console.log(`${this.name} says meow!`);
}
}
const oreo = new Cat("Oreo");
const felix = new Cat("Felix");
// Both cats share the same meow method
console.log(oreo.meow === felix.meow); // true
// But each has its own uniqueId method
console.log(oreo.uniqueId === felix.uniqueId); // false
Bottom Line
- Prototype methods (like
BetterCat.prototype.meow
) are more efficient - Instance methods (like
this.meow
) are good for custom behavior - Class methods are prototype methods by default - the best option!
By understanding the difference, you can write better JavaScript code that runs faster and uses less memory, whether you're building a simple cat app or something much bigger!
Top comments (0)