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.

6 min read

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.

prototypeproto
What it isA property on constructor functionsAn internal link on every object
Found onFunctions (except arrow functions) and classesEvery object
PurposeDefines what new instances will inherit fromPoints to the actual object this object inherits from
AccessSomeFunction.prototypeObject.getPrototypeOf(obj)
Standard?Yes, standard since ES1Legacy 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.

javascriptjavascript
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:

Constructor prototype to instance chain

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.

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.

javascriptjavascript
const parent = { color: "blue" };
const child = { __proto__: parent };
 
console.log(child.color); // "blue", inherited

When 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.

javascriptjavascript
function F() {}
const obj = new F();
 
console.log(Object.getPrototypeOf(obj) === F.prototype); // true
console.log(Object.getPrototypeOf([]) === Array.prototype); // true

That 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.

javascriptjavascript
function greet() {
  return "hello";
}
 
console.log(Object.getPrototypeOf(greet) === Function.prototype); // true
console.log(Object.getPrototypeOf(greet) === greet.prototype); // false

Every 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.

javascriptjavascript
const regular = function () {};
const arrow = () => {};
 
console.log(typeof regular.prototype); // "object"
console.log(arrow.prototype); // undefined

If 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.

javascriptjavascript
const arr = [1, 2, 3];
console.log(Object.getPrototypeOf(arr) === Array.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype)); // null

Array 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().

javascriptjavascript
const parent = { shared: true };
const child = Object.create(parent);
child.own = "value";
 
console.log(Object.getPrototypeOf(child) === parent); // true
console.log(child.shared); // true

Avoid 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

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.
RunePowered by Rune AI

Frequently Asked Questions

Should I use __proto__ in my code?

No. __proto__ is a legacy accessor that exists on Object.prototype. Use Object.getPrototypeOf() to read the prototype and Object.setPrototypeOf() to change it. The __proto__ key in object literals ({ __proto__: parent }) is the one standard use, but even that is niche.

Do arrow functions have a prototype property?

No. Arrow functions do not have a .prototype property because they cannot be used as constructors with new. Only regular function declarations, function expressions, and classes have .prototype.

Can I change an object's prototype after it is created?

Yes, with Object.setPrototypeOf(), but it is slow. JavaScript engines optimize objects based on their prototype at creation time. Changing the prototype later forces the engine to de-optimize. Set the prototype at creation time whenever possible.

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.