With bite-size code snippets and easy explanations. Introduction prototypes are confusing and unfamiliar to many developers and engineers. JavaScript Today, it’s time to demystify and master prototypes once and for all. Doing so will give us the confidence to deal with prototypes when we inevitably encounter and use them in JavaScript. Sections This guide is divided into the following sections. Effects of creating a function Invoking a function as a constructor Demonstration of prototypal inheritance Traversal of the prototype chain Components of the prototype chain A function’s prototype Prototypes without constructors Why is a prototype called a prototype? Tips on how to read this guide Each section builds on the previous one. As such, don’t skip sections, especially if you are reading this guide for the first time. All code snippets are relevant and are cumulative across sections. Code snippets should work well with recent versions of JavaScript. If you scroll through this guide too quickly, you may not gain much from it. Try to read this guide carefully and you will likely become convinced of what prototypes are and how to use them. It’s time to demystify and master prototypes once and for all. Effects of creating a function Creating a function has two effects. The function itself will be created.Note that a function is also an object and thus it can have additional properties. A second object will be created and become attached to the function as . <Function>.prototype To illustrate these effects, create a function named and observe that it automatically comes with a object. Person Person.prototype function Person(name) {this.name = name;} typeof Person.prototype; // "object" Invoking a function as a constructor When we invoke the function with the keyword, i.e. as a constructor, a new object is implicitly created, is set, and finally, is implicitly returned. Person new this this.name this function Person(name) {this.name = name;} const alex = new Person("Alex");typeof alex; // "object"alex.name; // "Alex" Demonstration of prototypal inheritance Importantly, the object and any other object constructed from will gain indirect access to . alex Person Person.prototype Let’s add a function to . Notice that the existing object can now , and a newly created object can do the same. This form of code reuse is known as prototypal inheritance. greet Person.prototype alex greet tom Person.prototype.greet = function() {console.log(`Hi ${this.name}`);} alex.hasOwnProperty("greet"); // falsealex.greet(); // "Hi Alex" const tom = new Person("Tom");tom.greet(); // "Hi Tom" Even though the object constructed from does not have a property on itself, it was able to access and thus invoke with being implicitly set to , which results in “Hi Alex” being logged to the console. alex Person greet Person.prototype Person.prototype.greet this alex The other object gains access to the object in a similar way. tom same Person.prototype Traversal of the prototype chain The traversal algorithm consults the object’s prototype when it cannot find the desired property on the object. If it finds the property on the prototype, the traversal stops. Otherwise, it will consult the prototype of the prototype, and so on, until it finds the property or it reaches the end of the prototype chain. At each traversal, the object the responsibility of doing something to its prototype if it does not know how to do it. did not know how to , so asked for help on how to . delegates alex greet alex Person.prototype greet Components of the prototype chain Let’s use to check ’s entire prototype chain. Object.getPrototypeOf alex Object.getPrototypeOf(alex) === Person.prototype; // true The line above tells us that the prototype of is . Therefore, if JavaScript cannot find the desired property on , it will check . alex Person.prototype alex Person.prototpe In other words, ’s prototype chain starts with . alex Person.prototype If JavaScript is still unable to find the desired property on , it will look at the prototype of , which is . Person.prototype Person.prototype Object.prototype Object.getPrototypeOf(Person.prototype) === Object.prototype; // true Why is the prototype of ? Object.prototype Person.prototype Suppose that , which is an object, was constructed from the built-in constructor (whether or not this is the case is an implementation detail). Person.prototype Object You can observe a pattern consistent with what we have learned so far. was constructed from .The prototype of is . alex Person alex Person.prototype was constructed from .The prototype of is . Person.prototype Object Person.prototype Object.prototype You can go from statement 1 to 2 by first substituting with , and then substituting with . Person Object alex Person.prototype To recap, we have seen that the prototype of is , and the prototype of is . Therefore, ’s prototype chain contains followed by . alex Person.prototype Person.prototype Object.prototype alex Person.prototype Object.prototype Is the final prototype in ’s prototype chain? Yes, because does not have a prototype (it is null). Object.prototype alex Object.prototype Object.getPrototypeOf(Object.prototype) === null; // true Even though is an object, its prototype is not , otherwise we will have an infinite prototype chain. Object.prototype Object.prototype Nearly all other objects in JavaScript have at the end of their prototype chains. We have seen how it is so for the object which was constructed from . This property also applies to plain objects created from the built-in constructor and the object literal syntax. Object.prototype alex Person Object const constructedObject = new Object();const objectLiteral = {}; Object.getPrototypeOf(constructedObject) === Object.prototype; // trueObject.getPrototypeOf(objectLiteral) === Object.prototype; // true The fact that nearly all objects have at the end of their prototype chains is of practical significance because they will have access to common utilities offered by such as and . Object.prototype Object.prototype toString valueOf alex.toString(); // "[object Object]"alex.valueOf(); // Person { name: "Alex" } A function’s prototype Earlier, we saw that has a property which can be accessed using . The syntax does not say anything more about , but we usually add more meaning to it. We think that is not just any random name that happens to be accessible at , but instead refers to . alex name alex.name alex alex.name alex.name Alex’s name What about ? Does it refer to ? Person.prototype Person ’s prototype Nope! Object.getPrototypeOf(Person) !== Person.prototype; // true If does not refer to ’s prototype, then whose prototype does it refer to? Person.prototype Person Well, will become the prototype of objects constructed from . We have already seen this behavior with . Person.prototype Person alex It may help to think of as a gift that Santa deposited at your house, but that gift is meant for your kids and is not yours. Person.prototype So what is the actual prototype of ? It is . Person Function.prototype Object.getPrototypeOf(Person) === Function.prototype; // true This is because is a and thus it has a prototype of . Person Function Function.prototype offers common utilities like , and which can be accessed from and other functions. Function.prototype call bind apply Person Prototypes without constructors We can also create prototype chains without constructors. const greeter = {greet() {console.log(`Hi ${this.name}`);}}; const bob = Object.create(greeter);bob.name = "Bob";bob.greet(); // "Hi Bob" Object.getPrototypeOf(bob) === greeter; // true In the above example, created a new object with as its prototype. That object was then assigned to . Although does not have its own function, it is able to access the function on its prototype . Object.create greeter bob bob greet greet greeter Creating a new object with a defined prototype using is more straightforward than having to deal with a constructor function and the object. Object.create <Constructor>.prototype The use of can be combined with factory functions. Unlike constructor functions, factory functions explicitly return an object and are not invoked with . Here is an example. Object.create new function createPerson(name, prototype) {const person = Object.create(prototype);person.name = name;return person;} const ada = createPerson("Ada", greeter);ada.greet(); // "Hi Ada" Given their simplicity and conciseness, the use of factory functions and tends to be the preferred approach over the use of constructor functions and the objects. Object.create <Constructor>.prototype Why is a prototype called a prototype? “Because someone came up with it” is not a satisfactory answer. The word is often glossed over in JavaScript literature. Most people treat it as a technical term and do not explain why it is suitably named “prototype”. Knowing why a prototype is called a prototype can give us a better mental model to work with whenever we encounter it. prototype That being said, it is hard to find an exact answer to this question. Here is my take on this question. A prototype in mainly refers to real life A product, albeit with limited features, where the final version of a product will share some characteristics of its prototype. After substituting the word “product” with “object”, we see that a JavaScript prototype refers to An object, albeit with limited features, where the final version of an object will share some characteristics of its prototype. Point 1 highlights a distinct point about prototypal inheritance as compared to traditional class-based inheritance. The prototype is an object that can be used on its own. However, a traditional class is not an object and thus cannot be used like an object. Note that although later versions of JavaScript have a keyword, it still uses prototypal inheritance under the hood. class Point 2 is valid because a prototype typically has fewer properties compared to an object that uses it as its prototype. For example, both and are able to (although does it with the help of ), but has an additional . alex Person.prototype greet alex Person.prototype alex name As for point 3, a JavaScript object does share some characteristics of its prototype(s) because of prototypal inheritance. Since objects are linked in the prototype chain, if you change a prototype, the behavior of existing and future objects linked to that prototype could be affected. As such, be careful not to change a built-in prototype unless you are trying to polyfill a standard feature. If everyone took the liberty of changing built-in prototypes arbitrarily, there will be conflicts and broken code. Summary You have seen what prototypes are, how JavaScript traverses the prototype chain to access prototype properties, and thus how code is reused in what we call prototypal inheritance. You have also seen how to use prototypes, with or without constructor functions. Though the mastery of prototypes has eluded many, I hope that this definitive guide has helped you to master prototypes in JavaScript and thus become a better software developer and engineer. Congratulations for making it all the way here! If you find this guide useful, send it to your colleagues and friends who may benefit from it. For further reading by Eric Elliott Common Misconceptions About Inheritance in JavaScript by Kyle Simpson You Don’t Know JS: & Object Prototypes this