Skip to main content

Prototypal Inheritance

OOP in JavaScript is built on prototypal inheritance. Objects can be chained so that a property not found in one object is automatically searched for in another. The link here is a special internal property, [[Prototype]], which is displayed as __proto__ in the browser console.

Object prototype

The Object.create(obj) method creates and returns a new object, linking it to the obj object.

const animal = {
legs: 4,
};
const dog = Object.create(animal);
dog.name = "Mango";

console.log(dog); // { name: 'Mango', __proto__: animal }
console.log(animal.isPrototypeOf(dog)); // true

The object referenced in __proto__ is called a prototype. In our example, the animal object is the dog object’s prototype. The isPrototypeOf() method checks if the animal object is dog’s prototype and returns true or false.

console.log(dog.hasOwnProperty("name")); // true
console.log(dog.name); // 'Mango'

console.log(dog.hasOwnProperty("legs")); // false
console.log(dog.legs); // 4

The dog.name reference is obvious: it returns the dog object’s own property, name . When accessing dog.legs, the interpreter looks for the legs property in the dog object, cannot find it and continues searching in the object by reference from dog.__ proto__, that is, in the animal object, its prototype.

The prototype is a backup storage of object properties and methods, which is automatically enabled when searching for them. An object that acts as a prototype can also have its own prototype, etc.

The property is searched for until the first match is found. The interpreter searches for a property by name in the object; if not found, it refers to the __proto__ property, that is, it follows the link to the prototype object, and then to the prototype of this prototype. If the interpreter gets to the end of the chain and does not find a property with the given name, it will return undefined.

Note

In the specification, the __proto__ property is denoted as [[Prototype]]. The double square brackets are important, as they indicate that this is an internal property.

hasOwnProperty() method

Now that you have learned about how to find properties of an object, you should understand why the for...in loop does not distinguish between properties of an object and its prototype.

const animal = { eats: true };
const dog = Object.create(animal);
dog.barks = true;

for (const key in dog) {
console.log(key); // barks, eats
}

This is why you use the obj.hasOwnProperty(prop) method, which returns true if the prop property belongs to the obj object, and not to its prototype; otherwise it returns false.

const animal = {
eats: true,
};
const dog = Object.create(animal);
dog.barks = true;

for (const key in dog) {
if (!dog.hasOwnProperty(key)) continue;

console.log(key); // barks
}

The Object.keys(obj) method will return an array of own keys of the obj object, which is why in practice it is used instead of for...in.

const animal = {
eats: true,
};
const dog = Object.create(animal);
dog.barks = true;

const dogKeys = Object.keys(dog);

console.log(dogKeys); // ['barks']