completefrontend
Open lab My progress
THE JAVASCRIPT FIELD GUIDE

The prototype chain

Learn how JavaScript property lookups walk from an object to its prototype, how shadowing works, how to tell own from inherited properties, and why this still points at the receiver in inherited methods.

By the end, you can
  • 01
    Follow a property readFollow rabbit → animal → Object.prototype → null and say what each read gives back.
  • 02
    Tell own from inheritedPick the right check: Object.hasOwn, in, hasOwnProperty, isPrototypeOf, or propertyIsEnumerable.
  • 03
    Use inherited methods safelyExplain why this in an inherited method is the object before the dot.

Prototype links

Every ordinary JavaScript object has a hidden link to one other object. The link is called [[Prototype]]. The double square brackets mean the link lives inside JavaScript. You cannot write rabbit.[[Prototype]] in your code.

When you read a property, JavaScript first looks on the object itself. If the property is not there, JavaScript follows the link to the other object and looks there. It keeps going, one link at a time. This path of linked objects is the prototype chain. The object at the other end of a link is called a prototype.

This lesson uses ideas from earlier lessons:

  • Object basics: the in operator, Object.hasOwn, and the toString method that every object seems to have.
  • Constructors & new: new links each new object to Constructor.prototype.
  • Methods & this, and The this keyword: the object before the dot becomes this.
  • Scope: how JavaScript finds variables.

Scope finds variables, like rabbit. The prototype chain finds properties, like rabbit.eats.

Real-life analogyThe shop, warehouse, and factory

You ask a shop for batteries. The clerk checks the shelf. The shelf is empty, so the clerk calls the warehouse. The warehouse is empty too, so it calls the factory. In the end, someone has batteries, or the answer is "Sorry, we don't stock it."

In real life: The shop shelf
In JavaScript: The object you read from
In real life: The warehouse
In JavaScript: That object's prototype
In real life: The factory behind the warehouse
In JavaScript: The prototype's prototype
In real life: Sorry, we don't stock it
In JavaScript: The search reaches null, so the value is undefined
The old __proto__ name

Older code reads and changes the link with obj.__proto__. This is an old accessor: a property that runs code when you read or set it. It lives on Object.prototype, so normal objects can use it. Objects made with Object.create(null) do not have it. In new code, use Object.getPrototypeOf, Object.setPrototypeOf, and Object.create. One form is still fine: writing { __proto__: animal } inside an object literal is part of the standard. The next example uses it.

Set the link inside an object literalPop out in the code editor (opens in a new tab)JavaScript
const animal = { eats: true };const rabbit = { __proto__: animal, jumps: true };console.log(Object.getPrototypeOf(rabbit) === animal);console.log(rabbit.eats);

Line 2 makes rabbit and points its link at animal. Line 3 prints true: Object.getPrototypeOf(rabbit) gives back the object at the other end of the link, which is animal. Line 4 prints true: rabbit has no eats, so JavaScript finds it on animal.

Reading rabbit.eats. The rabbit cart holds jumps: true but no eats. An arrow named [[Prototype]] goes from rabbit to the animal cart, which holds eats: true. So the read gives true.rabbit.eatsjumps: truerabbit1. no eats here[[Prototype]]eats: trueanimal2. found: true
rabbit has no eats of its own. JavaScript follows the link to animal and finds eats: true there.

Three Object methods work with the link:

  • Object.getPrototypeOf(obj) gives you the object at the other end of the link.
  • Object.create(proto) makes a new, empty object whose link points at proto.
  • Object.setPrototypeOf(obj, proto) changes the link of an object that already exists.
Read, create, and change the linkPop out in the code editor (opens in a new tab)JavaScript
const animal = { eats: true };const rabbit = Object.create(animal); console.log(Object.getPrototypeOf(rabbit) === animal);Object.setPrototypeOf(rabbit, null);console.log(rabbit.eats);console.log(Object.getPrototypeOf(rabbit) === null);

Line 4 prints true: the link points at animal. Line 5 sets the link to null, so now there is no next object. Line 6 prints undefined: rabbit has no eats, and there is nowhere left to look. Line 7 prints true.

JavaScript engines (the programs that run your code) work faster when an object keeps the same link. So set the link when you create the object, if you can.

Here is the simplest everyday use. One object holds a method, and another object uses it through the link.

A user finds greet on personPop out in the code editor (opens in a new tab)JavaScript
const person = {  greet() {    return "Hello";  },};const user = Object.create(person);console.log(user.greet());console.log(Object.hasOwn(user, "greet"));

Line 6 makes user with its link pointing at person. Line 7 calls user.greet(). user has no greet, so JavaScript finds it on person and prints Hello. Line 8 prints false: greet was not copied onto user.

Lookup & shadowing

STEP THROUGH

An object owns a property when the property is stored on the object itself. A property that JavaScript finds through the link is inherited. The step-through below uses two objects:

  • animal owns eats and a walk method.
  • rabbit owns jumps. Its link points at animal.

rabbit also finds toString. That method lives on Object.prototype, the built-in object that sits after animal in the chain.

Follow a property read
Step 0 of 7Ready
Your turn: follow the blue line

Guess what each line prints. Then step through and watch JavaScript go from rabbit to animal, to Object.prototype, and finally to null.

Running in
  1. script
Next: line 1
const rabbit = Object.create(animal);rabbit.jumps = true; console.log(rabbit.jumps);console.log(rabbit.eats);console.log(typeof rabbit.toString);console.log(rabbit.fly);
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
Change line 6: which property should rabbit read?

Changing the choice starts the replay again. Guess whether JavaScript finds a value before you step.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

A chain can have more than two objects. Here JavaScript checks dog, then animal, then Object.prototype.

Three objects in one chainPop out in the code editor (opens in a new tab)JavaScript
const animal = { sleeps: true };const dog = Object.create(animal);dog.barks = true; console.log(dog.barks);console.log(dog.sleeps);console.log(Object.getPrototypeOf(Object.getPrototypeOf(dog)) === Object.prototype);

Line 5 prints true from dog itself. Line 6 prints true from animal. Line 7 calls Object.getPrototypeOf twice. The first call gives animal. The second gives the prototype of animal, which is Object.prototype, so it prints true.

When a property is missing, JavaScript does not stop at the first object. It checks every object in the chain. Only when the next link is null does it give back undefined.

A property that no object hasPop out in the code editor (opens in a new tab)JavaScript
const animal = { sleeps: true };const dog = Object.create(animal); console.log(dog.flies);console.log("flies" in dog);

Line 4 prints undefined. Line 5 prints false: the in operator also searched the whole chain and found nothing.

Reading dog.flies. Four cards in a row joined by arrows: dog, animal, Object.prototype, and null. Under the first three it says no flies. Under null it says stop. The result is undefined.dog.fliesdoganimalObject.prototypenullno fliesno fliesno fliesstopdog.flies is undefined
JavaScript checks dog, then animal, then Object.prototype. None of them has flies, and the next link is null, so the answer is undefined.

Reading and writing work differently:

  • A read climbs the chain until it finds the property.
  • A normal write, like rabbit.eats = false, stores the property on the object before the dot. It does not change the prototype.
  • If an object owns a property with the same name as one further up the chain, JavaScript finds the own one first. We say the own property shadows the inherited one: it hides it.
Reads climb the chain, writes stay on rabbit
Step 0 of 7Ready
Your turn: follow the blue line

Watch how reads and writes differ. A read climbs the chain. A normal write puts the property on the object before the dot.

Running in
  1. script
Next: line 1
const rabbit = Object.create(animal); rabbit.eats = false;console.log(rabbit.eats);console.log(animal.eats); delete rabbit.eats;console.log(rabbit.eats);
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
After rabbit.eats = false. The rabbit cart now holds its own eats: false. The [[Prototype]] arrow still goes to the animal cart, which still holds eats: true.rabbit.eats = falseeats: falserabbitfound first[[Prototype]]eats: trueanimalnot changed
The write puts a new eats on rabbit. A read of rabbit.eats now stops at rabbit, and animal.eats stays true.
One exception: an inherited setter

A setter is a function that runs when you assign to a property. You write it with set. If the prototype has a setter for that name, the assignment calls the setter. It does not make a new property. Inside the setter, this is still the object you assigned to.

An inherited setter runs insteadPop out in the code editor (opens in a new tab)JavaScript
const animal = {  set mood(value) {    this.savedMood = value;  },};const rabbit = Object.create(animal);rabbit.mood = "curious";console.log(rabbit.savedMood);console.log(Object.hasOwn(rabbit, "mood"));

Line 7 runs the setter from animal, with this set to rabbit. So line 8 prints curious. Line 9 prints false: rabbit never got its own mood.

delete removes only a property that the object owns. It never touches the prototype. Once the own property is gone, the inherited one shows again.

Delete shows the prototype's value againPop out in the code editor (opens in a new tab)JavaScript
const person = { name: "Person" };const user = Object.create(person);user.name = "Asha";delete user.name; console.log(user.name);console.log(Object.hasOwn(user, "name"));

Line 3 gives user its own name. Line 4 deletes it. Line 6 prints Person, found on person. Line 7 prints false.

One more case. A property can be marked non-writable, which means its value cannot be changed. Object.defineProperty makes a property with settings like this. If the prototype has a non-writable property, a normal assignment to that name does nothing in a script without "use strict". It does not create an own property.

A read-only property on the prototypePop out in the code editor (opens in a new tab)JavaScript
const animal = {};Object.defineProperty(animal, "id", { value: 1, writable: false });const rabbit = Object.create(animal); rabbit.id = 2;console.log(rabbit.id);console.log(Object.hasOwn(rabbit, "id"));

Line 6 prints 1: the inherited id did not change. Line 7 prints false: rabbit has no own id. In strict mode, the same assignment throws a TypeError instead. Either way, the write did not create a shadow.

Own vs inherited properties

INTERACTIVE

An own property is stored on the object itself. An inherited property is found by following the link. You read both the same way, with a dot. So when it matters where a property is stored, you need a check.

Chain visualizer
Visualizer setupPop out in the code editor (opens in a new tab)JavaScript
const animal = { eats: true, walk() {} };const rabbit = Object.create(animal);rabbit.jumps = true; let current = rabbit;while (current !== null) {  // Check own properties, then climb.  current = Object.getPrototypeOf(current);}
Where JavaScript lookseats
  1. rabbitno eats here
  2. animaleats: true

JavaScript stops at the first object that has it.

Try it yourself
Try jumps, eats, toString, or fly.

JavaScript found eats on animal. Its value is true.

This tool walks the real chain. It moves one link at a time with Object.getPrototypeOf and checks each object with Object.hasOwn.
Real-life analogyA family recipe card

You can cook from the family recipe without having your own copy. If you write your own version and stick it on your fridge, you cook from that one first. Throw your note away, and you cook from the family binder again.

In real life: A recipe in the family binder
In JavaScript: An inherited method or value
In real life: Your handwritten version
In JavaScript: An own property that shadows it
In real life: Throwing away your version
In JavaScript: delete shows the inherited value again
Own or inherited?
  • rabbit.jumps after rabbit.jumps = true
  • rabbit.eats when only animal.eats exists
  • rabbit.toString, which every object seems to have
  • rabbit.fly when no object in the chain has it
  • rabbit.eats after rabbit.eats = false
  • rabbit.secret, a hidden property on animal
Try it yourself
0 of 6 correct

Sort each read by where JavaScript finds the property. The chain is rabbit, then animal, then Object.prototype.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Where a property is stored also changes which keys you get when you list them:

  • Object.keys(obj) lists only the keys the object owns.
  • for...in also lists keys from the prototypes.
  • Both skip keys that are marked non-enumerable, which means hidden from listing.

If you want only own keys in a for...in loop, check each key with Object.hasOwn.

Object.keys lists own keys; for...in lists morePop out in the code editor (opens in a new tab)JavaScript
const animal = { country: "India" };const rabbit = Object.create(animal);rabbit.name = "Asha"; console.log(Object.keys(rabbit).join(","));const keys = [];for (const key in rabbit) keys.push(key);console.log(keys.join(","));

Line 5 prints name. Lines 6 to 8 collect keys with for...in and print name,country. The key country came from animal.

Object.create(null) makes an object with no link at all, so its chain ends right away. This is handy for a dictionary: an object you use only to store keys and values. No extra names like toString come along. But it has no helper methods either. So call Object.hasOwn(settings, key), because settings.hasOwnProperty does not exist.

A dictionary with no prototypePop out in the code editor (opens in a new tab)JavaScript
const settings = Object.create(null);settings.theme = "light"; console.log(Object.hasOwn(settings, "theme"));console.log("toString" in settings);console.log(typeof settings.toString);

Line 4 prints true. Line 5 prints false, and line 6 prints undefined: there is no Object.prototype in the chain, so there is no toString to find.

hasOwnProperty, isPrototypeOf & propertyIsEnumerable

Each check answers a different question. Pick the one that matches what you want to know:

  • Is the property stored on this object?
  • Can JavaScript find the property anywhere in the chain?
  • Is this object somewhere in that object's chain?
  • Will the property show up when I list the keys?

Each row of the table is one check. Read across: what it answers, then when to use it.

Property checks compared
CheckWhat it answersWhen to use it
Object.hasOwn(obj, key)Is key stored on obj itself?Use it to check ownership. It works even when obj has no prototype.
obj.hasOwnProperty(key)Is key stored on obj itself?It works on normal objects. It is missing on objects with no prototype.
key in objCan JavaScript find key anywhere in the chain?Use it when an inherited property also counts.
proto.isPrototypeOf(obj)Is proto somewhere in the chain of obj?Use it to check how two objects are linked.
obj.propertyIsEnumerable(key)Is key stored on obj and shown in lists?It is false for inherited keys and for hidden keys.
Object.keys(obj)Which keys does obj store and show?It leaves out inherited keys.
for...inWhich keys show up, here and up the chain?Add an Object.hasOwn check inside to keep only own keys.
Every check on one chainPop out in the code editor (opens in a new tab)JavaScript
const animal = { eats: true };Object.defineProperty(animal, "secret", {  value: "warehouse",  enumerable: false,});const rabbit = Object.create(animal);rabbit.jumps = true; console.log(Object.hasOwn(rabbit, "jumps"));console.log(Object.hasOwn(rabbit, "eats"));console.log("eats" in rabbit);console.log(Object.keys(rabbit).join(","));console.log(animal.isPrototypeOf(rabbit));console.log(animal.propertyIsEnumerable("secret"));

Lines 2 to 5 add a secret property to animal. enumerable: false hides it from listing. Then the six lines print:

  • Line 9: true. rabbit owns jumps.
  • Line 10: false. eats is on animal, not on rabbit.
  • Line 11: true. in finds eats through the link.
  • Line 12: jumps. Only the own key is listed.
  • Line 13: true. animal is in the chain of rabbit.
  • Line 14: false. secret is hidden from listing.

Object.hasOwn is safer than obj.hasOwnProperty. It still works when the object has no prototype, and when the object has its own property named hasOwnProperty. propertyIsEnumerable is stricter than both. It is true only when the object owns the property and the property is not hidden from listing.

this in inherited methods

STEP THROUGH

A method can be found on a prototype and still work on the object before the dot. In rabbit.walk(), JavaScript finds walk on animal. But rabbit is before the dot, so this is rabbit.

The method is written inside the object on purpose. A minifier is a tool that makes code smaller before it goes live. It could move a separate function around and change what this shows in this demo.

this is the object before the dot
Step 0 of 6Ready
Your turn: follow the blue line

Step through a method that lives on the prototype. What matters is not where JavaScript found the method, but which object was before the dot.

Running in
  1. script
Next: line 1
  walk() {    this.isWalking = true;  },};const rabbit = Object.create(animal); rabbit.walk();console.log(rabbit.isWalking);console.log(animal.isWalking);
CallStoreChangeResultBlue line: runs next. Ran: already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
After rabbit.walk(). The walk method card is in the animal cart. The rabbit cart now holds isWalking: true, because this was rabbit during the call.rabbit.walk()isWalking: truerabbitthis = rabbit[[Prototype]]walk()animalwalk found here
JavaScript finds walk on animal. But rabbit is before the dot, so this is rabbit, and isWalking lands on rabbit.

This is why methods on a prototype are useful. One function can serve many objects, and each object keeps its own data, such as isWalking.

Where you’ll use this

The prototype chain explains things you use every day:

  • Every array has map, because map lives on Array.prototype.
  • Every date has toISOString, because it lives on Date.prototype.
  • Objects made with the same constructor share its methods.
  • A class stores each method once, not on every object.

The next lesson, F.prototype & constructors, shows how new sets this link.

Built-in objects use the same chain. An array links to Array.prototype. A function links to Function.prototype. Both of those link to Object.prototype.

Chains of built-in objectsPop out in the code editor (opens in a new tab)JavaScript
const scores = [10, 20];function greet() {} console.log(Object.getPrototypeOf(scores) === Array.prototype);console.log(Object.getPrototypeOf(greet) === Function.prototype);console.log(Object.getPrototypeOf(Array.prototype) === Object.prototype);

The chain can also cause bugs. If a prototype holds an array, every linked object uses that same array. Changing it through one object changes it for all of them.

Bug: two objects push into one shared arrayPop out in the code editor (opens in a new tab)JavaScript
const animal = { skills: [] };const rabbit = Object.create(animal);const fox = Object.create(animal); rabbit.skills.push("jump");fox.skills.push("sneak");console.log(rabbit.skills.join(","));

On line 5, rabbit has no own skills, so JavaScript finds the array on animal and pushes into it. Line 6 does the same for fox. Line 7 prints jump,sneak.

Fix: give each object its own array firstPop out in the code editor (opens in a new tab)JavaScript
const animal = { skills: [] };const rabbit = Object.create(animal);const fox = Object.create(animal); rabbit.skills = [];fox.skills = [];rabbit.skills.push("jump");fox.skills.push("sneak");console.log(rabbit.skills.join(","));

Lines 5 and 6 give each object its own new array. Now line 9 prints jump.

A factory is a function that makes and returns new objects. It can keep the shared methods on one prototype and give each new object its own data. This is usually clearer than changing links after the objects exist.

Shared methods, fresh data for each userPop out in the code editor (opens in a new tab)JavaScript
const userMethods = {  greet() {    return "Hi " + this.name;  },};function makeUser(name) {  const user = Object.create(userMethods);  user.name = name;  return user;}const user = makeUser("Asha");console.log(user.greet());console.log(Object.hasOwn(user, "greet"));

Line 12 prints Hi Asha. Line 13 prints false: greet is inherited, while name is own. Class objects work the same way: the methods sit on one prototype, and each object keeps its own data.

Speed and safety

Avoid Object.setPrototypeOf on objects that are already in use. Engines read properties faster when an object's link stays the same, and changing the link can undo that speed-up. Also be careful when you copy keys from user input into objects. A key such as __proto__ can reach a shared prototype and change what many objects inherit. This attack is called prototype pollution.

Common misconceptions

“Inherited properties are copied onto the object.”

Nothing is copied. The object keeps a link, and JavaScript follows the link when it needs to.

“in means the object owns the property.”

in is true when JavaScript can find the property anywhere in the chain. To check whether the object itself stores it, use Object.hasOwn.

“Assigning to an object changes its prototype.”

A normal assignment creates or changes a property on the object itself. The prototype stays the same. The one exception is an inherited setter.

“The scope chain and the prototype chain are the same.”

Scope finds variables, like rabbit. The prototype chain finds properties, like rabbit.eats.

“obj.__proto__ is the modern way to use the link.”

Writing __proto__ inside an object literal is standard. But reading or setting obj.__proto__ is old. Use the Object methods instead.

“Putting an array on a prototype is harmless.”

Sharing methods is good. But an array on a prototype is shared too, so every linked object changes the same array. Give each object its own array.

Practice: trace the chain

5 EXERCISES
Exercise 1 · Warm-upPredict the value after delete

Predict what the program prints.

Starter codePop out in the code editor (opens in a new tab)JavaScript
const animal = { eats: true };
const rabbit = Object.create(animal);
rabbit.eats = false;
delete rabbit.eats;
console.log(rabbit.eats);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeCount own and inherited keys

    Type both outputs, separated by a comma.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const animal = { eats: true, sleeps: true };
    const rabbit = Object.create(animal);
    rabbit.jumps = true;
    rabbit.eats = false;
    console.log(Object.keys(rabbit).length);
    console.log("sleeps" in rabbit);

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · ChallengeFix the shared array

      The starter prints jump,sneak. Change it so rabbit.skills prints only jump.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      const animal = { skills: [] };
      const rabbit = Object.create(animal);
      const fox = Object.create(animal);
      
      rabbit.skills.push("jump");
      fox.skills.push("sneak");
      console.log(rabbit.skills.join(","));
        Exercise 4 · PracticeChoose the right check

        Which method tells you whether animal is in the chain of rabbit?

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeExplain this in an inherited method

          After rabbit.walk() in the lesson's method example, where is isWalking created?

          Answer, then press Check. Spacing and letter case don’t matter.

            Quiz: check your understanding

            10 QUESTIONS

            For each code sample, ask two questions. Where is the property stored? Does the code read, write, delete, or call it?

            Lesson quiz · 10 questionsScore: first tries count
            1. Question 1 of 10What is an object's [[Prototype]]?

              Choose an answer to see the explanation.

            2. Question 2 of 10After the write to rabbit.eats, what does this print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const animal = { eats: true };
              const rabbit = Object.create(animal);
              rabbit.eats = false;
              console.log(animal.eats);

              Choose an answer to see the explanation.

            3. Question 3 of 10Which check also counts inherited properties?

              Choose an answer to see the explanation.

            4. Question 4 of 10What does this inherited method program print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const animal = { walk() { this.isWalking = true; } };
              const rabbit = Object.create(animal);
              rabbit.walk();
              console.log(Object.hasOwn(rabbit, "isWalking"));

              Choose an answer to see the explanation.

            5. Question 5 of 10Which sentence about __proto__ is true?

              Choose an answer to see the explanation.

            6. Question 6 of 10What does this shared array program print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const animal = { skills: [] };
              const rabbit = Object.create(animal);
              const fox = Object.create(animal);
              rabbit.skills.push("jump");
              fox.skills.push("sneak");
              console.log(rabbit.skills.join(","));

              Choose an answer to see the explanation.

            7. Question 7 of 10What does Object.keys(rabbit) include?

              Choose an answer to see the explanation.

            8. Question 8 of 10What does this Object.keys program print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const animal = { country: "India" };
              const rabbit = Object.create(animal);
              rabbit.name = "Asha";
              console.log(Object.keys(rabbit).join(","));

              Choose an answer to see the explanation.

            9. Question 9 of 10What does an object with no prototype print here?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const settings = Object.create(null);
              console.log(typeof settings.toString);

              Choose an answer to see the explanation.

            10. Question 10 of 10The prototype has a property that cannot be changed. What does this print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const animal = {};
              Object.defineProperty(animal, "id", { value: 1, writable: false });
              const rabbit = Object.create(animal);
              rabbit.id = 2;
              console.log(rabbit.id);

              Choose an answer to see the explanation.

            Key takeaways

            • [[Prototype]] is a hidden link from one object to another. JavaScript uses it to find properties.
            • A read checks the object first, then each prototype in turn. If the next link is null, the result is undefined.
            • An own property with the same name hides (shadows) the inherited one.
            • Object.hasOwn asks "Is it stored here?" in asks "Can JavaScript find it anywhere in the chain?"
            • An inherited method gets this from the object before the dot, so rabbit.walk() writes to rabbit.

            One-liner.
            The prototype chain is where JavaScript looks for a property: the object first, then its prototypes, and null at the end.

            Up next: F.prototype & constructors.

            CompleteFrontend Clear concepts. Working examples.