When I ask interview candidates to explain what prototypes mean in JavaScript, the response is often something like this
Here's my attempt to explain it succinctly.
I think it's important to draw the distinction between 2 related concepts: the prototype property of functions, and the prototype of an object
Every function in JavaScript has a prototype
property (which is an object). When a new object is created by invoking a function using the new
operator, e.g. invoking the function as a constructor, the resulting object has a hidden link to
that prototype
object. The prototype object to which the new object is linked can be described as the object's prototype.
Every object in JavaScript has a hidden link to the prototype property of the constructor function that created it.
Object literals (not created with a constructor function) have a hidden link to Object.prototype
, e.g. the protoype property
of Object
, which can be thought of as the mother of all constructor functions.
When looking up a property in an object, if the property is not found in the object itself, the JavaScript engine will then
look in the object's prototype. Since the prototype is itself an object, the same rules apply, in that if a property is
not found on the prototype, it will be looked up on its prototype. This chain continues until Object.prototype
is reached.
For example
function Dog(name) {
if (name) this.name = name;
}
// add properties to Dog's prototype property
Dog.prototype.bark = function() {
return "woof";
};
Dog.prototype.name = 'Fido'; // default name
If we invoke Dog
as a constructor with no name argument
var d = new Dog; // d now has a hidden link to Dog.prototype
console.log(d.name); // prints 'Fido' - d doesn't have a name property but it is found on Dog.prototype
console.log(d.bark()); // prints 'woof' - d doesn't have a bark property but it is found on Dog.prototype
If we invoke Dog
as a constructor with a name argument
var d = new Dog('Spot'); // d now has a hidden link to Dog.prototype
console.log(d.name); // prints 'Spot' - d has its own name property
console.log(d.bark()); // prints 'woof' - d doesn't have a bark property but it is found on Dog.prototype
delete d.name; // d no longer has its own name property
console.log(d.name); // prints 'Fido' - d "shines through" from Dog.prototype
Going up the chain...
// d doesn't have a toString property, and neither does Dog.prototype
// but toString is found on Object.prototype
console.log(d.toString()); // prints "[object Object]"