17/11/2024
JavaScript is known for its unique approach to inheritance, which is quite different from classical inheritance found in languages like Java or C++. Instead of using classes and instances, JavaScript relies on prototypes, creating a chain of objects that can inherit properties and methods. Let’s break down how prototypal inheritance works in JavaScript.
Every JavaScript object has an internal property called [[Prototype]]
(often accessible via __proto__
or Object.getPrototypeOf()
). This prototype property points to another object, which acts as a template. If you try to access a property that doesn't exist on an object, JavaScript will look up the prototype chain to find it.
const animal = { sound: 'generic sound', speak: function() { console.log(this.sound); } }; const dog = Object.create(animal); dog.sound = 'bark'; dog.speak(); // Output: 'bark'
In this example, dog
inherits from animal
. If dog
didn’t have the speak
method or the sound
property, JavaScript would look up the prototype chain to the animal
object.
You can create a new object using Object.create()
, which allows you to set the prototype of the newly created object to an existing one. This method is a direct way to establish a prototype relationship.
const cat = Object.create(animal); cat.sound = 'meow'; cat.speak(); // Output: 'meow'
Here, cat
inherits the speak
method from animal
and sets its own sound
property.
The prototype chain is crucial for understanding how JavaScript looks for properties and methods. If an object does not have a property, JavaScript checks its prototype, and if that prototype doesn’t have it either, it continues up the chain. This continues until it reaches null
, which signifies the end of the chain.
console.log(dog.hasOwnProperty('sound')); // Output: true console.log(dog.hasOwnProperty('speak')); // Output: false console.log(Object.getPrototypeOf(dog) === animal); // Output: true
In this case, dog
has its own sound
property but inherits speak
from animal
.
You can modify the prototype of an object even after it has been created, affecting all objects that inherit from that prototype. This can be a powerful feature but should be used with caution.
animal.walk = function() { console.log('Animal walking'); }; dog.walk(); // Output: 'Animal walking'
Now, both dog
and any other object inheriting from animal
have access to the walk
method.
JavaScript also employs constructor functions for creating multiple objects that share the same prototype. When using a constructor, you define a function and then create instances using the new
keyword.
function Animal(sound) { this.sound = sound; } Animal.prototype.speak = function() { console.log(this.sound); }; const bird = new Animal('chirp'); bird.speak(); // Output: 'chirp'
In this case, Animal.prototype
serves as the prototype from which all instances created with new Animal()
can inherit the speak
method.
With ES6, JavaScript introduced class
syntax, which provides a cleaner way to work with constructor functions and prototypal inheritance. Although it looks similar to classical inheritance, under the hood, it is still using prototypal inheritance.
class Animal { constructor(sound) { this.sound = sound; } speak() { console.log(this.sound); } } const fish = new Animal('blub'); fish.speak(); // Output: 'blub'
Here, the speak
method is defined in the prototype of the class Animal
.
Understanding prototypal inheritance provides a strong foundation for working with JavaScript. By leveraging prototypes, you can create efficient and reusable code patterns that enhance your development capabilities.
17/11/2024 | VanillaJS
17/11/2024 | VanillaJS
17/11/2024 | VanillaJS
29/10/2024 | VanillaJS
29/10/2024 | VanillaJS
29/10/2024 | VanillaJS
17/11/2024 | VanillaJS