When you access a property on an object, Javascript looks first directly on the object for any properties that have been added directly to the object (these are called "own" properties). If it doesn't find the property there, then it looks up the prototype chain.
So, when you do this:
var Triangle = new Shape();
console.log(Triangle.toString()); // 'Shape'
it looks for the .toString() property on the actual object named Triangle, but there is no property by that name directly on that object. So, since it didn't find anything on the object directly, it then looks on the prototype and it finds the Shape.prototype.toString() implementation there and that is what is executed.
A reference to the prototype is stored on the Triangle object when it is created. It is not stored in the .prototype property - that property is only used on the constructor. Instead, each JS version has its own way of storing a reference to the prototype and it has traditionally not been the same for all browsers and how it was stored was non-standard. It was originally meant only for internal use by the JS engine. For example, Chrome stores it on a property named obj.__proto__, but IE does not. To fix this lack of standardization, there is new method called obj.getPrototypeOf() which can now be used in modern browsers to get access to the prototype for a given object. In any case, the JS engine searches this prototype for you automatically when resolving property names that are not found on the actual object itself.
If you did this:
var Triangle = new Shape();
Triangle.toString = function() {
return 'Shape named Triangle';
}
console.log(Triangle.toString()); // 'Shape named Triangle'
Then, javascript would first find the toString() implementation that you attached directly to the object and it would execute that one rather than the one on the prototype.
[[Prototoype]]chain, not the public prototype. See also ECMA-262 13.2 Creating Function Objects.__proto__to it and sets it to Shape.prototype. Shape however only has an empty__proto__. The "prototype chain" uses__proto__, not prototype.__proto__."abc".__proto__ === String.prototype