post's image

Daily Depth #3: Prototype

Ghost wrote 2 months ago (May 15, 2025) with 236👁️ | 6 mins read

Prototypal Inheritance - Behind the Class Mask

Daily Depth #3: Unmasking JavaScript Prototypes

Welcome back to Daily Depth! Today, we're diving into the fascinating world of JavaScript prototypes. Understanding prototypes is crucial for grasping how objects inherit properties and methods in this dynamic language. It's a cornerstone of JavaScript's object-oriented programming paradigm.

What is a Prototype?

In JavaScript, every object has an internal property, often referred to as its prototype. This prototype is itself an object. When you try to access a property of an object, and if that property is not found directly on the object itself, JavaScript will look for the property on the object's prototype. If it's not found there, it will continue to look up the prototype chain.

Think of a prototype as a blueprint or a parent object from which other objects can inherit properties and behaviors.

The Prototype Chain

Every object in JavaScript (with the exception of the very first object in the chain) has a prototype. This prototype is also an object and thus can have its own prototype, and so on. This creates a chain of prototypes, known as the prototype chain.

When you try to access a property on an object, JavaScript traverses up this prototype chain until it finds the property or reaches the end of the chain. If the property is not found even at the end of the chain, it results in undefined.

Creating Objects and Their Prototypes

There are several ways to create objects in JavaScript, and the way you create them affects their prototype.

1. Using Object Literals:

When you create an object using an object literal ({}), its prototype is Object.prototype, which is the base object for all objects in JavaScript.

const myObject = {
  name: 'Example',
  sayHello: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

console.log(Object.getPrototypeOf(myObject) === Object.prototype); // Output: true

2. Using Constructor Functions (with new keyword):

When you use a constructor function along with the new keyword, the newly created object's prototype will be the prototype property of the constructor function.

function Dog(name, breed) {
  this.name = name;
  this.breed = breed;
}

Dog.prototype.bark = function() {
  console.log('Woof!');
};

const myDog = new Dog('Buddy', 'Golden Retriever');
myDog.bark(); // Output: Woof!
console.log(Object.getPrototypeOf(myDog) === Dog.prototype); // Output: true

In this case, myDog inherits the bark method from Dog.prototype.

3. Using Object.create():

The Object.create() method creates a new object with the specified prototype object and properties.

const animal = {
  speak: function() {
    console.log('Generic animal sound');
  }
};

const cat = Object.create(animal);
cat.speak(); // Output: Generic animal sound
console.log(Object.getPrototypeOf(cat) === animal); // Output: true

cat.name = 'Whiskers';
cat.speak = function() {
  console.log('Meow!');
};
cat.speak(); // Output: Meow! (own property overrides prototype property)

Here, cat's prototype is animal, and it initially inherits the speak method. We can also add own properties to cat that can override the prototype's properties.

4. Using Classes (Syntactic Sugar over Prototypes):

JavaScript classes introduced in ES6 provide a more familiar syntax for creating objects and dealing with inheritance, but they are still based on prototypes under the hood.

class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log('Generic animal sound');
  }
}

class Lion extends Animal {
  speak() {
    console.log('Roar!');
  }
}

const myLion = new Lion('Simba');
myLion.speak(); // Output: Roar!
console.log(Object.getPrototypeOf(Lion) === Animal); // Output: false (prototype of class is the function)
console.log(Object.getPrototypeOf(myLion) === Lion.prototype); // Output: true
console.log(Object.getPrototypeOf(Lion.prototype) === Animal.prototype); // Output: true

Here, Lion inherits from Animal through the prototype chain.

Accessing and Modifying Prototype Properties

You can access properties from the prototype chain just like own properties. When you modify a property on an object, it usually creates an own property on that object, shadowing any property with the same name in its prototype chain.

Object.prototype

Object.prototype is the top-level prototype in JavaScript's prototype chain. All objects (except those created with Object.create(null)) ultimately inherit from Object.prototype, which provides fundamental methods like toString(), hasOwnProperty(), etc.

__proto__ and Object.getPrototypeOf()

While you might encounter the __proto__ property (double underscore), it is generally recommended to avoid using it directly as it's considered non-standard and its behavior might vary across different JavaScript environments.

The standard way to access the prototype of an object is using Object.getPrototypeOf(object).

Prototypal Inheritance vs. Classical Inheritance

JavaScript uses prototypal inheritance, where objects inherit directly from other objects (prototypes). This is different from classical inheritance found in languages like Java or C++, where inheritance is based on classes. In JavaScript, classes are syntactic sugar over the prototypal inheritance mechanism.

Why are Prototypes Important?

Understanding prototypes is crucial because it helps you:

  • Understand how inheritance works in JavaScript.
  • Write more efficient code by placing shared methods on prototypes instead of defining them on every object instance.
  • Leverage the full power of JavaScript's object model.
  • Work effectively with existing JavaScript code and libraries.

Conclusion

Prototypes are a fundamental concept in JavaScript that enables objects to inherit properties and methods from other objects, forming a prototype chain. This mechanism is at the heart of JavaScript's object-oriented capabilities. Whether you're using object literals, constructor functions, Object.create(), or classes, understanding prototypes will deepen your knowledge of JavaScript and empower you to write more sophisticated and maintainable code.

Stay tuned for the next episode of Daily Depth as we explore another essential software development concept!