A prototype is like a relationship. An object can point to another object as its prototype. Consider the following example:
mario points to an object that does not have the
__proto__, also known as the object's prototype.
In the example above, you start by looking at the
mario wire leading to an object. You first look if this object has a
hasRedHat property. The answer is no, but it has a prototype. You then follow the
__proto__ wire that leads to another object (
human). You look at that object to see if it has the
hasRedHat property. The answer is yes, so you follow the
hasRedHat wire leading to
true. Therefore, the result of
Note that this does not mean that
mario has a
hasRedHat property. Its prototype object, the same one to which
human points, does. With
The Prototype Chain
Think of a prototype as a relationship between objects, in which one object points to another object as its prototype. This sequence of objects is known as the object's prototype chain and cannot be circular.
mario object, then in its prototype, then in the prototype of that object, and so on. You would only get
undefined if you ran out of prototypes and had not yet found the property you were looking for.
Consider the following example where both objects have a property called
mario did not have its own
hasRedHat property, you would have to look at the prototype. But since the object
mario points to has its own
hasRedHat property, you don't need to keep looking for the answer. Once you find the property, you stop the search.
If you want to check whether an object has its own property wire with a certain name, you can call the built-in function
hasOwnProperty. It returns
true for own properties and does not look at prototypes:
When you read a property that does not exist in an object, you keep looking for it in the prototype chain. If you do not find it, you get
However, when you write a property that does not exist in an object, the assignment creates the property on that object. Therefore, prototypes play no role in this case.
Consider the following example:
Before the assignment, both expressions result in
false. Then you execute this assignment:
Assignments occur on the object itself. So
mario.hasRedHat = true creates a new property of its own called
hasRedHat on the object to which
mario points. It has no effect on the prototype. As a result,
human.hasRedHat is still
mario.hasRedHat is now
The Object Prototype
The Object Prototype is a special object that is used as the default prototype of all objects.
Although you have created what appears to be an empty object,
obj.__proto__ is not
undefined. It has a hidden
__proto__ wire that points to the Object Prototype by default. This allows you to access built-in object methods:
These built-in properties are normal properties on the Object Prototype that you can access because the
mario object's prototype is the Object Prototype.
The Object Prototype is an object without a prototype. You will not need to create objects like this, but it is useful to know that it exists and that it is created by customizing the
The example above will produce an object that does not have a prototype and, as a result, does not even have built-in object methods.
Polluting the Prototype
The mutating of a shared prototype is called prototype pollution:
You have mutated the Object Prototype by adding the
vehicle property to it. As a result, any object will use the same
One more thing:
Browsing through the MDN documentation, you will encounter the
__proto__ to each object.
To solve this problem, the
new keyword before the function call, the object is created automatically, without having to return it from the function, and it becomes available as
Also, the object's
__proto__ will be set to whatever you add into the function's
prototype property, without having to manually set it.
The example above shows how the
prototype property of a function allows you to configure the
__proto__ of the objects you get with
class syntax with a constructor instead:
Despite the fact that the use of the
__proto__ syntax is discouraged, remember that under the hood,
mushroom1.consume() still finds the
consume property by searching it via
class syntax as a convention that hides both