PROTOTYPE AND PROTOTYPE CHAIN IN JAVASCRIPT
This note explains prototype and prototype chains in simple language.
Prototype is one of the most important ideas in JavaScript. At first it looks confusing, but the basic idea is actually simple:
An object can use not only its own properties, but also properties from another object connected to it. That connection is called a prototype.
1. What is a prototype?
The connection between objects is provided by a special internal property called [[Prototype]].
We do not usually change it directly. JavaScript uses it automatically when it looks for a property in an object.
Simple idea
If JavaScript does not find a property inside the current object, it checks the prototype object.
So the prototype works like a backup place for properties and methods.
Diagram 1. Main idea
Object
│
├─ own properties
│
└─ [[Prototype]]
└─ backup place for more properties
2. Creating an object with a prototype
To create a new object linked to another object, JavaScript uses:
Object.create(obj)
This method creates a new object and sets obj as its prototype.
Example
const animal = {
legs: 4,
};
const dog = Object.create(animal);
dog.name = "Aaron";
console.log(dog); // { name: "Aaron", [[Prototype]]: animal }
Explanation
Here:
animalis the prototypedogis the new objectdoghas its own propertynamedogcan also useanimal.legsthrough the prototype link
Diagram 2. dog and animal
animal
│
└─ legs: 4
dog
│
├─ name: "Aaron"
└─ [[Prototype]] → animal
3. How property lookup works
Look at this example:
const animal = {
legs: 4,
};
const dog = Object.create(animal);
dog.name = "Aaron";
console.log(dog.name); // "Aaron"
console.log(dog.legs); // 4
What happens?
dog.name
JavaScript looks inside dog and finds:
name: "Aaron"
So it returns "Aaron".
dog.legs
JavaScript looks inside dog, but dog does not have its own legs property.
Then JavaScript checks dog[[Prototype]], which points to animal.
Inside animal, it finds:
legs: 4
So it returns 4.
Diagram 3. Property lookup
dog.legs
↓
look inside dog
↓
not found
↓
go to dog[[Prototype]]
↓
animal.legs
↓
4
4. Checking whether one object is the prototype of another
If you want to check whether one object is the prototype of another, use:
objA.isPrototypeOf(objB)
This checks whether objA is the prototype of objB.
Example
const customer = {
username: "Jacob",
};
const animal = {
legs: 4,
};
const dog = Object.create(animal);
dog.name = "Aaron";
console.log(animal.isPrototypeOf(dog)); // true
console.log(dog.isPrototypeOf(animal)); // false
console.log(customer.isPrototypeOf(dog)); // false
Explanation
animal.isPrototypeOf(dog)istruebecausedogwas created fromanimaldog.isPrototypeOf(animal)isfalsebecause the direction is wrongcustomer.isPrototypeOf(dog)isfalsebecausecustomeris not connected todog
Diagram 4. Prototype direction
animal → prototype of dog
dog → not prototype of animal
5. Own properties and inherited properties
A property can be:
- own — belongs directly to the object
- inherited — comes from the prototype
Example
const animal = {
legs: 4,
};
const dog = Object.create(animal);
dog.name = "Aaron";
console.log(dog.name); // "Aaron"
console.log(dog.legs); // 4
Explanation
nameis an own property ofdoglegsis an inherited property ofdog, because it comes fromanimal
Diagram 5. Own vs inherited
dog
│
├─ own property:
│ └─ name: "Aaron"
│
└─ inherited property from prototype:
└─ legs: 4
6. Checking own properties with hasOwnProperty()
To check whether an object has its own property, use:
obj.hasOwnProperty(key)
It returns:
trueif the property belongs directly to the objectfalseif the property comes from the prototype or does not exist
Example
const animal = {
legs: 4,
};
const dog = Object.create(animal);
dog.name = "Aaron";
console.log(dog.hasOwnProperty("name")); // true
console.log(dog.hasOwnProperty("legs")); // false
Explanation
namebelongs directly todoglegsdoes not belong directly todog; it comes fromanimal
Diagram 6. hasOwnProperty()
dog.hasOwnProperty("name") → true
dog.hasOwnProperty("legs") → false
7. Iterating over properties and the for...in problem
The for...in loop goes through both:
- own properties
- inherited properties
This is often inconvenient, because usually we want only own properties.
Example
const animal = { legs: 4 };
const dog = Object.create(animal);
dog.name = "Aaron";
for (const key in dog) {
console.log(key); // "name" "legs"
}
Explanation
for...in prints both:
"name"— own property"legs"— inherited property
Diagram 7. for...in behavior
for...in over dog
↓
"name"
"legs"
8. How to iterate only over own properties
If you use for...in, add a check with hasOwnProperty().
Example
const animal = { legs: 4 };
const dog = Object.create(animal);
dog.name = "Aaron";
for (const key in dog) {
if (dog.hasOwnProperty(key)) {
console.log(key); // "name"
}
}
Now only the property that belongs directly to dog is printed.
Diagram 8. Filtering only own properties
for...in
↓
check hasOwnProperty(key)
│
├─ true → use it
└─ false → skip it
9. Better way: Object.keys() and Object.values()
In practice, developers usually use:
Object.keys(obj)Object.values(obj)
These return only own keys or only own values. They do not include inherited properties.
Example
const animal = { legs: 4 };
const dog = Object.create(animal);
dog.name = "Aaron";
console.log(Object.keys(dog)); // ["name"]
console.log(Object.values(dog)); // ["Aaron"]
for (const key of Object.keys(dog)) {
console.log(key); // "name"
}
This is why Object.keys() with for...of is often preferred over for...in.
Diagram 9. Better iteration
Object.keys(dog)
↓
["name"]
Object.values(dog)
↓
["Aaron"]
10. Prototype chains
A prototype can also have its own prototype.
That means JavaScript can build a prototype chain.
Example
const objC = { c: "objC prop" };
const objB = Object.create(objC);
objB.b = "objB prop";
const objA = Object.create(objB);
objA.a = "objA prop";
console.log(objA); // { a: "objA prop", [[Prototype]]: objB }
console.log(objB); // { b: "objB prop", [[Prototype]]: objC }
console.log(objC); // { c: "objC prop", [[Prototype]]: Object }
Explanation
Here we have a chain:
objA → objB → objC → Object
So:
objAcan use its own propertyaobjAcan also usebfromobjBobjAcan also usecfromobjC
Diagram 10. Prototype chain
objA
│
├─ a: "objA prop"
└─ [[Prototype]] → objB
│
├─ b: "objB prop"
└─ [[Prototype]] → objC
│
├─ c: "objC prop"
└─ [[Prototype]] → Object
11. Access through the prototype chain
Example
const objC = { c: "objC prop" };
const objB = Object.create(objC);
objB.b = "objB prop";
const objA = Object.create(objB);
objA.a = "objA prop";
console.log(objA.hasOwnProperty("a")); // true
console.log(objA.a); // "objA prop"
console.log(objA.hasOwnProperty("b")); // false
console.log(objA.b); // "objB prop"
console.log(objA.hasOwnProperty("c")); // false
console.log(objA.c); // "objC prop"
console.log(objA.hasOwnProperty("x")); // false
console.log(objA.x); // undefined
Explanation
JavaScript searches in this order:
objAobjBobjCObject- if still not found →
undefined
Diagram 11. Property search path
objA.x
↓
check objA
↓
check objB
↓
check objC
↓
check Object
↓
not found
↓
undefined
12. End of the prototype chain
At the end of the prototype chain there is always a reference to the base object class.
For plain objects, the chain ends at Object.
Example
const objB = {
b: "objB prop",
};
const objA = Object.create(objB);
objA.a = "objA prop";
console.log(objA);
If you expand this in the browser developer console, you can see that:
objApoints toobjBobjBpoints toObject- after that, the chain ends
Diagram 12. End of the chain
objA
↓
objB
↓
Object
↓
end of chain
13. Easy memory rules
Prototype = backup place for properties
Own property = belongs directly to the object
Inherited property = comes from prototype
Prototype chain = object → prototype → prototype of prototype
End of chain = Object
14. Quick summary
Object.create(obj)creates a new object withobjas prototype[[Prototype]]is used automatically during property lookupisPrototypeOf()checks prototype relationshipshasOwnProperty()checks whether a property belongs directly to the objectfor...inincludes inherited propertiesObject.keys()andObject.values()return only own properties- property lookup moves through the prototype chain until a match is found or
undefinedis returned - the chain for normal objects ends at
Object
15. Final conclusion
Prototype is the mechanism that lets one object use properties from another object.
If you understand:
- what
[[Prototype]]is - how
Object.create()works - the difference between own and inherited properties
- why
hasOwnProperty()matters - how property lookup moves through the chain
- why the chain ends at
Object
then you already understand one of the most important parts of JavaScript objects.