Understanding the prototype property in JavaScript
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. Theclass
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 thetoString
method from the car object's prototype ifcar
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 ofCar.prototype
. This allows setting up prototype chain for new objects. Note thatnew Car()
only makes sense whenCar
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 thetoString
function withthis
value set to"abc"
. This allows code reuse - executing the same code lines with different value ofthis
. 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.
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(...)
.
Semantic Versioning Cheatsheet
Learn the difference between caret (^) and tilde (~) in package.json.