Every function in JavaScript automatically gets a property called prototype. When you use a function as a constructor (with the new keyword), JavaScript sets the new object’s [[Prototype]] to that function’s prototype object.
Example:
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log("Hello, I'm " + this.name);
};
var user = new Person("Alice");
user.sayHello(); // Hello, I'm Alice
Here’s what’s happening behind the scenes:
- We create a constructor function
Person. - We add a method
sayHellotoPerson.prototype. - When we call
new Person("Alice"):- A new object is created.
- Its
[[Prototype]]is set toPerson.prototype. thisis bound to the new object.
So when user.sayHello() is called, JavaScript looks for sayHello:
- It’s not on
user, so… - It looks at
Person.prototypeand finds it there.
The Prototype Chain
A key idea behind JavaScript’s inheritance model is the prototype chain, which is really just a linked list of objects.
For example:
console.log(user.__proto__);
// Person.prototype
console.log(user.__proto__.__proto__);
// Object.prototype
console.log(user.__proto__.__proto__.__proto__);
// null
The chain looks like:
user → Person.prototype → Object.prototype → null
Each step is a fallback where JavaScript looks for properties.
Why Use Prototypes?
1. Memory Efficiency
Methods placed on prototypes are shared among all instances.
Instead of:
function User() {
this.sayHi = function() { ... };
}
You should use:
User.prototype.sayHi = function() { ... };
This prevents storing the same function multiple times.
2. Inheritance
Prototypes give you a simple way to “inherit” functionality.
Example:
function Animal() {}
Animal.prototype.eat = function() {
console.log("Eating...");
};
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
var rex = new Dog();
rex.eat(); // Inherited from Animal