Prototypes and Constructors

Back

Loading concept...

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?

  1. dog looked for speak() in itself - not found!
  2. dog asked its parent pet - found it!
  3. dog used 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)
  • this refers 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!

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.