Objects: Prototypes and Constructors
The Family Tree of Objects
Imagine you have a family tree. Your grandparents passed down traits to your parents, and your parents passed them down to you. You have your dad’s eyes, your mom’s smile, and grandma’s talent for cooking!
JavaScript objects work exactly the same way. Every object can have a “parent” that shares its abilities. This parent is called a prototype.
What is a Prototype?
Think of a prototype as a blueprint locker. When you can’t find something in your own backpack, you check the shared locker.
const pet = {
speak() {
return "Some sound!";
}
};
const dog = {
breed: "Golden Retriever"
};
// Make 'pet' the parent of 'dog'
Object.setPrototypeOf(dog, pet);
// dog doesn't have speak(), but its
// parent 'pet' does!
console.log(dog.speak());
// Output: "Some sound!"
What happened?
doglooked forspeak()in itself - not found!dogasked its parentpet- found it!dogused the parent’s method
The Prototype Chain
What if grandpa has something, but dad doesn’t? You can still inherit it!
The prototype chain is like climbing a family tree:
graph TD A["Your Object"] -->|"Can't find it?"| B["Parent Prototype"] B -->|"Still can't find?"| C["Grandparent Prototype"] C -->|"Keep going..."| D["Object.prototype"] D -->|"End of the line"| E["null"]
Real Example:
const grandparent = {
lastName: "Smith"
};
const parent = {
job: "Teacher"
};
const child = {
name: "Emma"
};
Object.setPrototypeOf(parent, grandparent);
Object.setPrototypeOf(child, parent);
// Emma climbs the family tree:
console.log(child.name);
// "Emma" - found in child
console.log(child.job);
// "Teacher" - found in parent
console.log(child.lastName);
// "Smith" - found in grandparent!
Object.getPrototypeOf
Want to know who your object’s parent is? Use Object.getPrototypeOf()!
It’s like asking: “Who gave you that trait?”
const animal = { alive: true };
const cat = { name: "Whiskers" };
Object.setPrototypeOf(cat, animal);
// Who is cat's parent?
const catParent = Object.getPrototypeOf(cat);
console.log(catParent === animal);
// true - animal is cat's parent!
console.log(catParent.alive);
// true
Important: Every object’s ultimate ancestor is Object.prototype:
const myObj = {};
const parent = Object.getPrototypeOf(myObj);
console.log(parent === Object.prototype);
// true - the original ancestor!
Constructor Functions
Imagine you’re a factory owner. You need to make 1000 toy robots. Would you build each one from scratch? No way! You’d create a machine (constructor) that builds robots for you.
A constructor function is that machine!
// Constructor = Factory Machine
function Robot(name, color) {
this.name = name;
this.color = color;
this.greet = function() {
return `Beep! I am ${this.name}!`;
};
}
// Make robots!
const robot1 = new Robot("Bolt", "blue");
const robot2 = new Robot("Spark", "red");
console.log(robot1.greet());
// "Beep! I am Bolt!"
console.log(robot2.color);
// "red"
Key Points:
- Constructor names start with Capital Letter (Robot, not robot)
thisrefers to the new object being created- Each robot gets its own copy of properties
The new Keyword
The new keyword is the magic button that activates the factory machine.
What new does (4 secret steps):
graph TD A["1. Creates empty object {}"] --> B["2. Links prototype"] B --> C["3. Runs constructor with 'this'"] C --> D["4. Returns the new object"]
Without new - DISASTER!
function Car(brand) {
this.brand = brand;
}
// With new - works perfectly
const car1 = new Car("Toyota");
console.log(car1.brand); // "Toyota"
// Without new - broken!
const car2 = Car("Honda");
console.log(car2); // undefined!
// 'this' went to the wrong place
Remember: Always use new with constructor functions!
The instanceof Operator
After the factory makes a robot, how do you check if it really came from that factory?
Use instanceof - it’s like checking the factory stamp!
function Dog(name) {
this.name = name;
}
function Cat(name) {
this.name = name;
}
const buddy = new Dog("Buddy");
const whiskers = new Cat("Whiskers");
// Check the factory stamps
console.log(buddy instanceof Dog);
// true - buddy came from Dog factory
console.log(buddy instanceof Cat);
// false - buddy didn't come from Cat
console.log(whiskers instanceof Cat);
// true - whiskers came from Cat
Bonus: instanceof checks the whole family tree!
console.log(buddy instanceof Object);
// true - all objects descend from Object!
new.target
What if someone forgets to use new? The factory machine breaks!
new.target is a security guard that checks if new was used.
function Superhero(name) {
// Security check!
if (!new.target) {
throw new Error(
"You forgot 'new'! Try: new Superhero()"
);
}
this.name = name;
this.power = "flying";
}
// Correct way
const hero1 = new Superhero("Flash");
console.log(hero1.name); // "Flash"
// Wrong way - security guard catches it!
try {
const hero2 = Superhero("Batman");
} catch(e) {
console.log(e.message);
// "You forgot 'new'!"
}
Smart Pattern: Auto-fix missing new:
function SmartPerson(name) {
if (!new.target) {
// Fix it automatically!
return new SmartPerson(name);
}
this.name = name;
}
// Both work now!
const p1 = new SmartPerson("Alice");
const p2 = SmartPerson("Bob");
console.log(p1.name); // "Alice"
console.log(p2.name); // "Bob"
Putting It All Together
Let’s build a complete example using everything we learned:
// 1. Constructor Function
function Pokemon(name, type) {
// 6. new.target safety
if (!new.target) {
return new Pokemon(name, type);
}
this.name = name;
this.type = type;
}
// 2. Add to prototype (shared!)
Pokemon.prototype.attack = function() {
return `${this.name} attacks!`;
};
// 4. Create with 'new'
const pikachu = new Pokemon("Pikachu", "Electric");
const charizard = new Pokemon("Charizard", "Fire");
// 3. Prototype chain in action
console.log(pikachu.attack());
// "Pikachu attacks!"
// Check prototype
console.log(
Object.getPrototypeOf(pikachu) === Pokemon.prototype
);
// true
// 5. instanceof check
console.log(pikachu instanceof Pokemon);
// true
Quick Summary
| Concept | What It Does | Analogy |
|---|---|---|
| Prototype | Shared parent object | Family locker |
| Prototype Chain | Lookup path for properties | Family tree |
| getPrototypeOf | Find an object’s parent | “Who’s your parent?” |
| Constructor | Factory that creates objects | Robot factory |
| new | Activates the factory | Magic button |
| instanceof | Checks factory origin | Factory stamp |
| new.target | Checks if new was used | Security guard |
You Did It!
Now you understand how JavaScript objects inherit from each other, just like a family tree! You know how to:
- Create parent objects with prototypes
- Walk the prototype chain
- Find parents with getPrototypeOf
- Build factories with constructor functions
- Use the new keyword correctly
- Check origins with instanceof
- Guard constructors with new.target
You’re now a JavaScript inheritance expert!
