JS __proto__ vs prototype: What Is the Difference?
The two prototype properties confuse every JavaScript developer at some point. Learn what each one means, where it lives, and how they connect objects to their shared behavior.
The two prototype-related terms in JavaScript look like they should be the same thing, but they are not. The prototype property only exists on functions. The internal prototype link, exposed through proto, exists on every object instead. Confusing them is one of the most common stumbling blocks for intermediate JavaScript developers.
| prototype | proto | |
|---|---|---|
| What it is | A property on constructor functions | An internal link on every object |
| Found on | Functions (except arrow functions) and classes | Every object |
| Purpose | Defines what new instances will inherit from | Points to the actual object this object inherits from |
| Access | SomeFunction.prototype | Object.getPrototypeOf(obj) |
| Standard? | Yes, standard since ES1 | Legacy accessor; getPrototypeOf is preferred |
prototype: The Blueprint on Constructors
Every function that can be called with new has a prototype property, and that property is an object. When you call new on that function, the newly created object's internal prototype link is set to point at it.
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
return `Hi, I am ${this.name}`;
};
const alice = new Person("Alice");
console.log(alice.greet()); // "Hi, I am Alice"The prototype object on Person is an ordinary object. Adding methods to it makes them available to every instance created with new Person(). Alice does not have her own greet method; JavaScript finds it by walking up the chain to the shared prototype.
The diagram makes the relationship visual:
The function's prototype property and the instance's internal prototype link point to the same object. The function defines it. The instance links to it.
proto: The Link on Every Object
The proto accessor exposes the internal prototype link that exists on almost every object. You can read and, in theory, write it, but both are discouraged in favor of the standard Object.getPrototypeOf() and Object.setPrototypeOf() methods.
const parent = { color: "blue" };
const child = { __proto__: parent };
console.log(child.color); // "blue", inheritedWhen you access a property on child, JavaScript first looks for it on child itself. It is not there, so it follows the internal prototype link to parent, finds the property there, and returns it. This is the prototype chain: a linked list of objects that JavaScript walks until it finds the property or reaches the end.
The Key Rule
For any object created with a constructor, the object's internal prototype link is the constructor's prototype property. This holds whether you use a class, a regular function with new, or a built-in constructor.
function F() {}
const obj = new F();
console.log(Object.getPrototypeOf(obj) === F.prototype); // true
console.log(Object.getPrototypeOf([]) === Array.prototype); // trueThat rule holds for every built-in type as well. An array's internal prototype link points to Array.prototype, a date's points to Date.prototype, and so on for every constructor JavaScript ships with.
What prototype Is NOT
A common misconception is that the prototype property is the prototype of the function itself. It is not: a function's own prototype, meaning where the function inherits from, is Function.prototype.
function greet() {
return "hello";
}
console.log(Object.getPrototypeOf(greet) === Function.prototype); // true
console.log(Object.getPrototypeOf(greet) === greet.prototype); // falseEvery function's own internal prototype link points to Function.prototype, because functions inherit methods like call and apply from there. The prototype property is a separate object that only matters when the function is used as a constructor.
Arrow Functions Have No prototype
Arrow functions cannot be used with new, so they do not have a prototype property.
const regular = function () {};
const arrow = () => {};
console.log(typeof regular.prototype); // "object"
console.log(arrow.prototype); // undefinedIf you try to use an arrow function as a constructor, JavaScript throws a type error. This is one reason to choose a regular function or a class when you need to create instances.
The Full Prototype Chain
Every object in JavaScript is connected through its internal prototype link, forming a chain that ends at null. An array's chain goes through Array.prototype, then Object.prototype, then null.
const arr = [1, 2, 3];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype)); // nullArray methods like map and filter live on Array.prototype. General object methods like hasOwnProperty and toString live on Object.prototype. Every array inherits both sets of methods through the chain.
Setting the Prototype at Creation Time
The best time to set an object's prototype is when you create it, using Object.create().
const parent = { shared: true };
const child = Object.create(parent);
child.own = "value";
console.log(Object.getPrototypeOf(child) === parent); // true
console.log(child.shared); // trueAvoid Object.setPrototypeOf() after creation unless you have no other option. Changing the prototype of an existing object disrupts engine optimizations and can make property access noticeably slower.
Rune AI
Key Insights
- prototype is a property on constructor functions. It defines the object that new instances will inherit from.
- proto is the internal link on every object pointing to its actual prototype.
- For an instance created with new F(), instance.proto === F.prototype.
- Use Object.getPrototypeOf(), not proto, to read an object's prototype.
- Arrow functions have no .prototype because they cannot be constructors.
Frequently Asked Questions
Should I use __proto__ in my code?
Do arrow functions have a prototype property?
Can I change an object's prototype after it is created?
Conclusion
prototype is a property on constructor functions that defines what new instances will inherit from. proto is the actual internal link on every object that points to what it inherits from. Function.prototype defines the prototype chain. instance.proto walks it. Keeping the two straight is the key to understanding how JavaScript shares behavior across objects.| When you need to | Use |
|---|---|
| Set up what instances of a constructor will inherit | Add methods to Constructor.prototype |
| Read the prototype of any object | Object.getPrototypeOf() |
| Create an object with a specific prototype | Object.create() |
| Check if one object is in another's chain | isPrototypeOf() |
For a deeper look at how this chain works in practice, see the prototype chain article. For how constructors and classes use prototypes, start with JavaScript classes.
More in this topic
Using Decorators for Logging in JS Architecture
Learn how JavaScript decorators wrap class methods to add logging without touching the original code, including setup with Babel and how execution order works.
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.