A JavaScript object has a link to another object called its prototype. When a property or method is not found on the object, JavaScript follows that link, continuing along the prototype chain until it finds the member or reaches the end. This lets objects share behavior without each defining its own copy. An object literal can call an inherited method such as toString() even when the literal does not define it. section 4.2
Inspecting a shared prototype
In index.js, two object literals can be checked with `Object.getPrototypeOf(hat) === Object.getPrototypeOf(boots)`. The comparison is true. Changing `toString` through that shared prototype changes the method both objects use—not just the method used by `hat`. section 4.2.1
Be careful when changing a prototype shared by unrelated objects. A replacement toString() that expects name and price properties will not suit every object. For objects known to have those properties, define a dedicated prototype and assign it with Object.setPrototypeOf(). That prototype can itself have a prototype, so lookup still follows a chain. section 4.2.2
Listing 4.6 Using a custom prototype in the index.js file in the primer folder
let ProductProto = {
toString: function() {
return `toString: Name: ${this.name}, Price: ${this.price}`;
}
}
let hat = {
name: "Hat",
price: 100,
getPriceIncTax() {
return Number(this.price) * 1.2;
}
};
let boots = {
name: "Boots",
price: 100,
getPriceIncTax() {
return Number(this.price) * 1.2;
}
}
Object.setPrototypeOf(hat, ProductProto);
Object.setPrototypeOf(boots, ProductProto);
console.log(hat.toString());
console.log(boots.toString());
The index.js listing assigns one custom prototype to two product objects, giving each the same toString() implementation without changing the prototype used by other object literals. section 4.2.2
A constructor function combines object creation, property setup, and prototype assignment through `new`. The function sets each new object’s properties through `this`; methods intended for all its objects go on the function’s `prototype` property. For example, `Product.prototype.toString = function() { ... }` supplies the method used by objects created with `new Product(...)`. section 4.2.3
To build an inheritance chain with constructor functions:
- Call the base constructor with the new object as `this`, as in `Product.call(this, name, price)`, so its properties are initialized. section 4.2.4
- Link the prototype objects—not the constructor functions—with `Object.setPrototypeOf(TaxedProduct.prototype, Product.prototype)`. A method on the first prototype can then find a method on the second. section 4.2.4
- A nearer method with the same name shadows one farther along the chain. To build on the shadowed method, call it through the prototype that defines it, such as `Product.prototype.toString.call(this)`. section 4.2.4
Use `instanceof` with a constructor to check whether its prototype occurs in an object’s chain. For a direct prototype check without a constructor, use `isPrototypeOf` on the prototype object. section 4.2.5
JavaScript class syntax uses this same prototype system. Class methods are added to the prototype assigned to instances; `extends` and `super` provide class syntax for inheritance and calling superclass behavior. Understanding prototypes therefore helps explain what a class instance inherits and why an overridden method runs. section 4.2.7


