Understanding the prototype property in JavaScript

NAVIGATION

Prototypal inheritance

JavaScript features that make inheritance work

An example

Misleading prototype property name

You’re having difficulty understanding the prototype property in JavaScript. You know it has got to do with object-oriented programming (OOP) and object inheritance, but you're not sure of the mechanics of how it works.

Prototypal inheritance

Object-oriented programming can be implemented in many ways. Other languages, such as Java, use class-based model where the language separates classes and instances of objects. In JavaScript there aren't any classes, but instead everything is an object. Inheritance in JavaScript is based on prototypal inheritance where objects inherit directly from other objects. An object contains reference to its ancestor in inheritance hierarchy - the prototype of the object.

ES6 introduced the class keyword into the language. It did not, however, introduce a new model of object-oriented inheritance. The class keyword provides syntactic sugar for expressing prototype properties and constructor functions as described in this article.

JavaScript features that make inheritance work

There are few language features that in concert make inheritance work.

  • Accessing a non-existent property from a JavaScript object causes the runtime to look for a match in the object's prototype. For example car.toString() results in using the toString method from the car object's prototype if car itself doesn't contain such method. The search continues recursively to the prototype of the prototype until a match is found or the chain is exhausted.
  • Calling new Car() creates a new object with prototype set to the value of Car.prototype. This allows setting up prototype chain for new objects. Note that new Car() only makes sense when Car is a function. Such function is also known as a constructor function.
  • Calling a function property of an object, the value of this is bound to the containing object. For example "abc".toString() calls the toString function with this value set to "abc". This allows code reuse - executing the same code lines with different value of this. A function property of an object is also called a method.

An example

Let's create an example that calculates the perimeter of a rectangle with object-oriented programming.

function Rectangle(x, y) {
  this.x = x;
  this.y = y;
}

Rectangle.prototype.perimeter = function() {
  return 2 * (this.x + this.y);
};

const rect = new Rectangle(1, 2);
console.log(rect.perimeter()); // outputs '6'

First a constructor function Rectangle is defined. The convention is to capitalize function names that are to be called with new to separate them from other functions. The constructor function is initially given an empty object as the value of this and the code populates it with x and y properties for later use.

Then, a function property is added to Rectangle.prototype that calculates the perimeter using the object's x and y properties. Notice the use of this that allows the same code to work on multiple objects with different values for the variables.

Finally, a new Rectangle object called rect is created. It inherits from Rectangle.prototype and allows us to call rect.perimeter() and print the results to the console.

Misleading prototype property name

There is something misleading in JavaScript regarding prototypes. The prototype of an object is not the same thing as the prototype property of the object. The former is used when looking up non-existent properties in the prototype chain. The latter is used for objects created using new, it will be the prototype of the newly created object. Understanding this difference allows you to fully understand the prototype property in JavaScript.

In our example, Rectangle.prototype will be the the prototype value used for objects created with new Rectangle() and the prototype of Rectangle itself is actually JavaScript's internal Function.prototype.

The value holding the prototype of an object is sometimes called the internal prototype link. It's also been historically called __proto__, a name that has some controversy. To be politically correct, it can be called the value that's returned from Object.getPrototypeOf(...).

Node doesn't wait for your database call to finish?

Node doesn't wait for your database call to finish?

Learn how asynchronous calls work and make your app run as you intended. Get short email course on asynchronicity and two chapters from Finish Your Node App.

Loading Comments