Understanding JavaScript Prototypes and the Prototype Chain: A Comprehensive Guide
This article explains JavaScript objects, various ways to create them, the role of prototypes and the hidden __proto__ property, and how the prototype chain enables inheritance, illustrated with clear code examples and diagrams for front‑end developers.
As a front‑end beginner, the concept of the prototype chain can seem confusing; this guide organizes notes on prototypes, objects, and inheritance in JavaScript.
1. Prototype
Object
An Object is a composite data type that stores unordered key‑value pairs. Each property consists of a key (property name) and a value, which can be any data type, including other objects.
Objects are composed of properties, each with a key and a value.
Property values may be primitives, arrays, or other objects.
Creating Objects
There are several ways to create objects:
Object literal
The most common and concise method uses {} to enclose key‑value pairs:
let person = {
name: 'John',
age: 30,
greet: function() {
console.log('Hello ' + this.name);
}
};name , age , greet are property names.
'John' , 30 , and the function are property values.
greet is a method; functions can be stored as object properties.
Using new Object()
You can also create an object with the constructor syntax:
let person = new Object();
person.name = 'John';
person.age = 30;
person.greet = function() {
console.log('Hello ' + this.name);
};This approach is slightly longer and less common because the literal syntax is clearer.
Using a constructor function
Define a constructor function to initialize objects:
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
console.log('Hello ' + this.name);
};
}
let person1 = new Person('John', 30);
let person2 = new Person('Alice', 25);this binds properties and methods to the newly created object.
Person is the constructor used to create person1 and person2 .
When many objects share the same structure, using a constructor avoids repeating the same code for each instance.
However, each instance gets its own copy of the greet function, which can waste memory.
2. Implicit Prototype (__proto__)
Every JavaScript object has a hidden __proto__ property that points to the prototype of the constructor that created it. This implicit prototype provides the lookup direction for the prototype chain.
For example, obj3.__proto__ === Test.prototype evaluates to true .
Practice
function Test(name, age) {
this.name = name;
this.age = age;
}
Test.prototype.say = function() {
console.log('I can speak');
};
var obj3 = new Test('Jack', 26);
// Questions:
// 1. What is the constructor? What is the instance?
// 2. obj3.constructor === Test ? (true)
// 3. obj3.__proto__ === Test ? (false)
// 4. Test.prototype === obj3.__proto__ ? (true)
// 5. obj3.__proto__.constructor === Test ? (true)3. Prototype Chain
Object.prototype
All objects ultimately inherit from Object.prototype , which sits at the top of the prototype chain. It provides common methods such as toString() , valueOf() , and hasOwnProperty() .
Even Test.prototype has its own __proto__ pointing to Object.prototype :
Test.prototype.__proto__ === Object.prototype // trueThus, every object’s lookup path ends at Object.prototype , whose __proto__ is null , marking the end of the chain.
Chain Traversal
When accessing a property, JavaScript first checks the object itself, then follows the __proto__ links upward until the property is found or the chain ends with null . If the property is not found, undefined is returned and a call to a non‑function throws an error.
Summary
Every JavaScript object has a prototype object accessed via the prototype property of its constructor, enabling inheritance.
Objects also have an implicit prototype ( __proto__ ); only function objects have a prototype property.
The hidden __proto__ provides the direction for prototype‑chain lookup, not the prototype property.
Multiple prototypes linked through __proto__ form the prototype chain.
Property and method lookup follows the prototype chain until it reaches null .
Prototype objects are key to inheritance, dynamic method addition, and sharing properties across instances.
If you have further questions or want to dive deeper into any part, feel free to discuss in the comments.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.