Tutorial

Objects, Prototypes and Classes in JavaScript

Published on January 10, 2019
author

Vijay Prasanna

Objects, Prototypes and Classes in JavaScript

Considering the fact that almost everything in JavaScript is an object, object oriented JavaScript code is very different from other object-capable languages. The JS object system is more of a prototype-based object system instead.

Coming from a C++ background, I was aware of the Object Oriented programming paradigm and had a very rigid idea of how Objects and Classes should work. Exposure to other languages like Java only seemed to further establish this idea. While these languages have their own semantics on how objects and classes work; Javascript, for the new user, is quite a revelation.

First off the bat, JavaScript objects are very different in the way they are created. There is no requirement for a class. Object instances can be created using the new operator:

let Reptile = new Object() {
 // ...
}

or with a function constructor

function Reptile() {
 // ...
}

Second, JavaScript objects are very flexible. While classic object oriented languages allow only property modification or property slots, JavaScript allows objects to modify their properties and methods; i.e. JavaScript objects have both property and method slots.

My first thought at the discovery was “yeah freedom!” but this came with a cost - a need to understand the prototype property in JavaScript. The knowledge of the prototype is essential to a developer who wishes to implement any semblance of an object oriented system in JavaScript.

All JavaScript objects are created from the Object constructor:

var Reptile = function(name, canItSwim) {
  this.name = name;
  this.canItSwim = canItSwim;
}

And the prototype allows us to add new methods to objects constructors, this means that the following method now exists in all instances of Reptile.

Reptile.prototype.doesItDrown = function() {
  if (this.canItSwim) {
    console.log(`${this.name} can swim`);
  } else {
    console.log(`${this.name} has drowned`);
  }
};

Object instances of Reptile can be now created:

// for this example consider alligators can swim and crocs cannot
let alligator = new Reptile("alligator", true);
alligator.doesItDrown(); // alligator can swim

let croc = new Reptile("croc", false); 
croc.doesItDrown(); // croc has drowned

The prototype of the Reptile object is now the basis for inheritance, the doesItDrown method is accessible to both alligator and croc because the prototype of Reptile has this method. The prototype property is shared amongst all its instances and is accessible via the __proto__ property of a particular instance.

Now, because of the existence of method slots and a common prototype instance property being shared across all instances, some very neat tricks are possible which are very weird to C++ folks:

croc.__proto__.doesItDrown = function() {
  console.log(`the croc never drowns`);
};

croc.doesItDrown(); // the croc never drowns
alligator.doesItDrown(); // the croc never drowns

Change one instance’s prototype property or method, all instances of the object are affected. This means we could be deleting stuff as well. A croc tired of drowning could potentially do this:

delete croc.__proto__.doesItDrown
alligator.doesItDrown();

//TypeError: alligator.doesItDrown
// is not a function

Now no one gets to swim.

This is just a silly example to show how fundamental the prototype is to the Object system in JavaScript and how it can be quite jarring to people from other object oriented languages.

With the ES6 syntax, JavaScript has been provided the feature to create classes.

However, the concept of true classes does not exist in JavaScript but it is emulated through prototype and the class syntax is just syntactic sugar around it. Therefore, understanding this behavior is important to realize the convenience and limitations of ES6 classes.

With the new class syntax, Reptile would be defined as:

class Reptile {
  constructor (name, canItSwim) {
    this.name = name;
    this.canItSwim = canItSwim;
  }

  doesItDrown () {
   if(this.canItSwim) 
    console.log(`${this.name} can swim`);
   else
    console.log(`${this.name} has drowned`);
  }
}

let alligator = new Reptile("alligator", true);
alligator.doesItDrown(); //alligator can swim

This does not mean it brings nothing new to the offer for prototype users, some pitfalls can be avoided by using ES6 classes, like making the new keyword mandatory for creating instances.

let croc = Reptile("croc", false);
//TypeError: Class constructor Reptile cannot be invoked without 'new'

This is actually a good thing, since it prevents accessing the wrong context when using the object properties and methods, which is usually the global scope or the window object.

In Conclusion

Though JavaScript right now does certainly lack features like truly private members. It has made creating objects via class syntax, instead of prototypes closely resemble classes from other OO languages like C++/Java.


PS. There has been a proposal to TC39 for creating truly private members in JavaScript classes, you can follow it here and contribute your opinion. If it were to be included in the next revision, then we’d have something like:

class Foo {
  #a; #b; // # indicates private members here
  #sum = function() { return #a + #b; };
}

// personally this format reminds me of $variable in PHP.
// I'm not sure if that's a good thing 

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

Learn more about our products

About the authors
Default avatar
Vijay Prasanna

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


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!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

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 SMBs

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.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.