Core Principles of Prototype Chains
Prototype chain comprehension requires accepting certain foundational JavaScript design principles:
Function Prototype Property
When a function is defined, JavaScript automatically adds a prototype property with a default value of an empty Object instance (except for the Object constructor itself).
function Example() {}
// Internal: this.prototype = {}
Object proto Property
When an object is created, JavaScript automatically adds a __proto__ property with a default value equal to its constructor's prototype.
function Constructor() {}
const instance = new Constructor();
// Internal: this.__proto__ = Constructor.prototype
Special Cases
Object Constructor:
function Object() {}
// Internal: this.prototype includes built-in methods
// constructor, hasOwnProperty, toString, etc.
Function Constructor:
const Function = new Function();
// Internal: this.__proto__ = Function.prototype
Key Relationships
-
Function prototype objects typically reference empty Object instances (Object constructor being the exception)
-
All functions are instances of Function (including Funcsion itself)
Function.__proto__ === Function.prototype
CustomFunction.__proto__ === Function.prototype
Object.__proto__ === Function.prototype
- Prototype object inheritance chain:
Function.prototype.__proto__ === Object.prototype
CustomFunction.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ === null
- Instance creation relationships:
const customInstance = new CustomFunction();
customInstance.__proto__ === CustomFunction.prototype
const objInstance = new Object();
objInstance.__proto__ === Object.prototype
Prototype Chain Termination
- Object.prototype represents the end of the prototype chain (references null)
- Newly created instances reside at the bottom of the chain
Core Mechanism
An object's implicit prototype (__proto__) equals its constructor's explicit prototype. Property lookup traverses the __proto__ chain upward until found or reaching null.
Prototype Methods and this Context
function Human(name, age) {
this.name = name;
this.age = age;
}
Human.prototype.updateName = function(newName) {
console.log(this); // References calling instance
this.name = newName;
};
const person = new Human('John', 25);
person.updateName('Mike');
console.log(person); // {name: 'Mike', age: 25}
instanceof Operator Mechanics
The instanceof operator checks if an object's prototype chain contains the specified constructor's prototype.
Object instanceof Function; // true
Object instanceof Object; // true
Practical Example: Property Lookup
function Sample() {}
Object.prototype.methodA = function() {
console.log('methodA()');
};
Function.prototype.methodB = function() {
console.log('methodB()');
};
const sampleInstance = new Sample();
sampleInstance.methodA(); // Works: sampleInstance -> Sample.prototype -> Object.prototype
// sampleInstance.methodB(); // Fails: methodB not in prototype chain
Sample.methodA(); // Works: Sample -> Function.prototype -> Object.prototype
Sample.methodB(); // Works: Sample -> Function.prototype
The lookup path:
sampleInstance->Sample.prototype->Object.prototypeSample->Function.prototype->Object.prototype