VOOZH about

URL: https://www.digitalocean.com/community/tutorials/understanding-prototypes-and-inheritance-in-javascript

⇱ Understanding Prototypes and Inheritance in JavaScript | DigitalOcean


Understanding Prototypes and Inheritance in JavaScript

Updated on August 26, 2021
👁 Understanding Prototypes and Inheritance in JavaScript

Introduction

JavaScript is a prototype-based language, meaning object properties and methods can be shared through generalized objects that have the ability to be cloned and extended. This is known as prototypical inheritance and differs from class inheritance. Among popular object-oriented programming languages, JavaScript is relatively unique, as other prominent languages such as PHP, Python, and Java are class-based languages, which instead define classes as blueprints for objects.

In this tutorial, we will learn what object prototypes are and how to use the constructor function to extend prototypes into new objects. We will also learn about inheritance and the prototype chain.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

Tutorial Series: How To Code in JavaScript

JavaScript is a high-level, object-based, dynamic scripting language popular as a tool for making webpages interactive.

About the author(s)

Software engineer and open source creator

Community and Developer Education expert. Former Senior Manager, Community at DigitalOcean. Focused on topics including Ubuntu 22.04, Ubuntu 20.04, Python, Django, and more.

Still looking for an answer?

Was this helpful?

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Could you please put this part a bit more clear ? - “This prototype chain is only one link long. x -> Object. We know this, because if we try to chain two [[Prototype]] properties together, it will be null.

This article is not as good as the others. It’s a bit confusing, because the author doesn’t explain the concept or prototyping and the reasons behind it.

I am just learning about prototypes, but one part of this didn’t seem right to me, and after trying out some things I think I can explain what I mean. It’s this part:

// Link prototypes and add prototype methods
Warrior.prototype = Object.create(Hero.prototype);
Healer.prototype = Object.create(Hero.prototype);

This isn’t really linking the objects, it’s more like replacing them. The point of the prototype chain as far as I can tell is that you can link them to form a kind of inheritance, without losing attributes, but this will lose them. Here’s what I mean:

function Hero(name, level){
 this.name = name;
 this.level=level;
}

function Healer(name, level, spell){
 Hero.call(this, name, level);
	this.spell = spell;
}

Hero.prototype.greet = function(){return "I am " + this.name}
Healer.prototype.heal = function(){return this.name + " casts " + this.spell}

var healer = new Healer("Pyro", 126, "Resta");

healer.heal()
// "Pyro casts Resta"
healer.greet() // undefined, as expected, not linked yet
// VM1872:1 Uncaught TypeError: healer.greet is not a function

// Now "link" the prototypes
Healer.prototype = Object.create(Hero.prototype)

healer.greet() // healer linked to old Healer prototype still, have to construct it again to pick up the change
// VM1872:1 Uncaught TypeError: healer.greet is not a function

healer = new Healer("Pyro", 126, "Resta");
healer.greet()
// "I am Pyro"
healer.heal() // oops
// VM2045:1 Uncaught TypeError: healer.heal is not a function

healer.constructor // Thinks its constructor is hero's
// ƒ Hero(name, level){
// this.name = name;
// this.level=level;
// }

So, as you can see, swapping out prototypes can lead to some really strange behavior. I found this out the hard way trying examples in this article.

Now, if you changed my example to define methods on Hero’s prototype first, then copy Hero’s to Healer’s, then define new methods on Healer’s, that works, but that is unnecessarily finicky seems to defeat the purpose of inheritance.

Another problem with the way in the article is that “Healer.prototype” begins with a reference to the “Healer” constructor. When you override the “prototype” property, “Healer.prototype.constructor” now point’s to “Hero’s” constructor. This makes things pretty ambiguous, because now healer, created with Healer’s constructor, thinks its constructor is actually Hero’s.

Rather, I think you should set the [[Prototype]] property of Healer’s prototype to point to Hero’s prototype. See this example for what seem like a better way to me:

function Hero(name, level){
 this.name = name;
 this.level=level;
}

function Healer(name, level, spell){
 Hero.call(this, name, level);
	this.spell = spell;
}

Hero.prototype.greet = function(){return "I am " + this.name}
Healer.prototype.heal = function(){return this.name + " casts " + this.spell}

var healer = new Healer("Pyro", 126, "Resta");

healer.heal()
// "Pyro casts Resta"
healer.greet() // undefined, as expected
// VM1872:1 Uncaught TypeError: healer.greet is not a function

// Instead of setting Healer.prototype, we're setting [[Prototype]] of Healer.prototype
Object.setPrototypeOf(Healer.prototype, Hero.prototype);

healer.greet() // This is now found, by traversing the prototype chain. You don't have to reassign healer. 
// "I am Pyro"
healer.heal() // healer's prototype is still Healer.prototype so this is fine
// "Pyro casts Resta"

// because prototypes are linked properly, children of Hero automatically obtain new methods defined on Hero
Hero.prototype.charge=function(){return "CHARGE!!"}
healer.charge() // didn't need to change anything on healer object or Healer function
// "CHARGE!!"
healer.constructor // healer still has proper constructor
// ƒ Healer(name, level, spell){
// Hero.call(this, name, level);
//	this.spell = spell;
// }

This seems to work a lot better: the order in when you declare things doesn’t matter, Healer’s prototype information is preserved. When you look at the structure of the object in the console, you see what looks more like proper inheritance. Let me know what you think.

Hey! There is a slight bug in your example code.

Warrior.prototype = Object.create(Hero.prototype) would actually replace all of the contents of the original Warrior prototype. Methods can be restored with proper sequence of statements in code. But what cannot be restored is a constructor property, which in turn is used by things like instanceof.

This could result into something like:

const warrior = new Warrior();
console.log(warrior instanceof Hero); // true
console.log(warrior instanceof Warrior); // false

That is, the prototype chain is broken, which is most probably not what we intended.

What one should do instead is:

Warrior.prototype.__proto__ = Object.create(Hero.prototype);

That would properly link Warrior to Hero’s whatever prototype chain correctly.

Also, you can safely get rid of Object.create() because this intermediate empty object doesn’t add any value.

So finally constructor function prototype’s linkage would look something like this:

Warrior.prototype.__proto__ = Hero.prototype;

In fact, if you look inside objects created with new ES2015 class syntax from class hierarchies using extend, you will find out that prototypes are linked exactly that way.

Also, it would be quite nice if you would explain the exact difference between prototype and __proto__ properties. It can be a source of greate confusion for the beginners. Especially when encountered in expressions like Warrior.prototype.__proto__ = Hero.prototype.

Uma delicia de conteudo. mulher é demais

Nice content! Very helpful :)

Just a heads-up: I guess “Object.setPropertyOf()” should be “Object.setPrototypeOf()” here

We will use to link the properties in the Hero constructor to the Warrior and Healer constructors, making sure to put it before any additional methods.

thanks a lot i had struggled so much to understand this topic but this was hella helpful thank you

👁 Creative Commons
This work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.
  • Deploy on DigitalOcean

    Click below to sign up for DigitalOcean's virtual machines, Databases, and AIML products.

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and AI-native businesses

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Start building today

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.

© 2026 DigitalOcean, LLC.Sitemap.
Dark mode is coming soon.