Skip to content
Lesson 8 of 15

Step 1 of 7 · Reading · ~4 min

Learn

Objects in Depth

The Prototype Chain

Every JavaScript object can point at another object, its prototype, and property lookup follows those links. The class keyword (taught in the custom-error-classes lesson) is a friendlier way to set them up, not a different system. By the end of this lesson you can draw the chain behind any object, predict where a property will be found, and explain what instanceof really tests.

Objects link to other objects

javascript

Reading a property walks outward: the object itself, then its prototype, then that object's prototype, and so on until it finds the name or reaches null (the end), which gives undefined.

Writing never walks. bike.wheels = 2 creates an own property on bike that shadows the inherited one; vehicle is untouched, and delete bike.wheels would reveal 4 again. Methods found up the chain still run with this set to the object you called them on (bike), which is why describe printed 2.

To ask whether a name is the object's own or inherited, use Object.prototype.hasOwnProperty.call(obj, "name"), and Object.getPrototypeOf(obj) to step up one link.

The top of the chain

A plain {} has Object.prototype as its prototype, which holds toString, hasOwnProperty and the other things every object seems to have. Its own prototype is null. You can build an object that has no prototype at all:

javascript

Constructor functions build the same links

A function called with new (rule 3 of the previous lesson) links the new object to the function's prototype property. Setting that property up by hand shows the chain being built:

javascript

The chain is c -> Circle.prototype -> Shape.prototype -> Object.prototype -> null. Only name is an own property of c; methods live once on the prototypes and every instance shares them. Two similar names cause endless confusion: Circle.prototype is a property of the constructor, naming the object that future instances will link to, while Object.getPrototypeOf(c) is the link of an instance. What new Circle("disc") does is: create an empty object linked to Circle.prototype, run the constructor with this set to it, and return it. A class ... extends declaration builds exactly these links with less typing.

instanceof and isPrototypeOf

c instanceof Shape asks: is Shape.prototype somewhere along c's chain? It is, so true. Shape.prototype.isPrototypeOf(c) asks the same question about any two objects, with no constructor involved.

A shared-prototype trap

Everything on a prototype is shared. That is perfect for methods and a bug for mutable data:

javascript

Per-instance data belongs in the constructor (this.items = []).

Common mistakes

  • Putting arrays or objects on a prototype and sharing them by accident.
  • Changing Object.prototype, which affects every object in the program.
  • Expecting obj.x = 1 to change the prototype's x. It adds an own property.
  • Using for...in and being surprised it lists inherited enumerable names; Object.keys gives own names only.
  • Calling obj.hasOwnProperty on an object made with Object.create(null).
  • Mixing up Fn.prototype and the actual prototype of an instance.

Your exercise

The starter builds a family of objects with Object.create from a small description and asks questions about them. You write the three helpers that walk the chain by hand.

Up nexttry / catch / throwError Handling

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…