- Home
- /
- Tutorials
- /
- JavaScript Tutorial
- /
- JavaScript Prototype Chain
JavaScript Classes
JavaScript Prototype Chain
Every object has a prototype, and lookups walk up the chain until they find a match.
This is the machinery classes are built on.
Understanding it explains why inheritance behaves the way it does.
Example
Example
javascript
class Animal {
speak() {
return "sound";
}
}
const dog = new Animal();
console.log(Object.getPrototypeOf(dog) === Animal.prototype);The instance's prototype is the class's prototype object.
How Lookup Works
Reading a property checks the object itself first.
If it is not there, JavaScript checks the prototype, then its prototype, and so on.
The chain ends at null, and the result is undefined.
Syntax
Syntax
javascript
Object.getPrototypeOf(object);Methods live on the prototype, not on the instance.
Methods Are Not on the Instance
This is why Object.keys never lists them.
Example
Example
javascript
class Person {
constructor(name) {
this.name = name;
}
greet() {
return "hi";
}
}
const ada = new Person("Ada");
console.log(Object.keys(ada).join(","));
console.log(typeof ada.greet);Only name is an own property, but greet is still callable.
hasOwnProperty
This distinguishes an object's own properties from inherited ones.
Example
Example
javascript
class Person {
constructor(name) {
this.name = name;
}
greet() {
return "hi";
}
}
const ada = new Person("Ada");
console.log(ada.hasOwnProperty("name"));
console.log(ada.hasOwnProperty("greet"));The output is true then false.
The Chain with Inheritance
Each extends adds another link.
Example
Example
javascript
class Animal {
breathe() {
return "breathing";
}
}
class Dog extends Animal {
bark() {
return "woof";
}
}
const rex = new Dog();
console.log(rex.bark() + " and " + rex.breathe());bark was found on Dog and breathe one link further up.
Shadowing
An own property hides one further up the chain.
The prototype's version is untouched for everyone else.
Example
Example
javascript
class Animal {
speak() {
return "generic";
}
}
const a = new Animal();
const b = new Animal();
a.speak = function () {
return "just for a";
};
console.log(a.speak() + " / " + b.speak());The output is just for a / generic.
The End of the Chain
Everything eventually reaches Object.prototype and then null.
Example
Example
javascript
const plain = {};
console.log(Object.getPrototypeOf(plain) === Object.prototype);
console.log(Object.getPrototypeOf(Object.prototype));The output is true then null.
Complete Example
Complete Example
html
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Prototype Chain</title>
</head>
<body>
<h1>The Prototype Chain</h1>
<p id="out"></p>
<script>
class Animal {
breathe() {
return "breathing";
}
}
class Dog extends Animal {
bark() {
return "woof";
}
}
const rex = new Dog();
const lines = [
"own properties: " + JSON.stringify(Object.keys(rex)),
"has bark of its own: " + rex.hasOwnProperty("bark"),
"can bark: " + (typeof rex.bark === "function"),
"is an Animal: " + (rex instanceof Animal)
];
document.getElementById("out").innerHTML = lines.join("<br>");
</script>
</body>
</html>Try It Yourself
Run the above example in the Try It Editor.
Try adding an own method:
Assign rex.bark = function () {} and watch hasOwnProperty change.
Important Points
- Property lookup walks up the prototype chain.
- Methods live on the prototype, not the instance.
hasOwnPropertytells own from inherited.- An own property shadows one further up the chain.
- The chain ends at
null.
Conclusion
The prototype chain is what classes are made of.
It explains shared methods, inheritance and why Object.keys skips them.
Knowing it turns class behaviour from rules to remember into something obvious.
